3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2006-2010 Nokia Corporation
6 * Copyright (C) 2004-2010 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
39 #include <dbus/dbus.h>
41 #include "lib/bluetooth.h"
43 #include "lib/sdp_lib.h"
46 #include "gdbus/gdbus.h"
49 #include "src/shared/util.h"
50 #include "src/shared/att.h"
51 #include "src/shared/queue.h"
52 #include "src/shared/gatt-db.h"
53 #include "src/shared/gatt-client.h"
54 #include "src/shared/gatt-server.h"
55 #include "src/shared/ad.h"
56 #include "btio/btio.h"
58 #include "attrib/att.h"
61 #include "gatt-database.h"
62 #include "attrib/gattrib.h"
64 #include "gatt-client.h"
67 #include "dbus-common.h"
69 #include "uuid-helper.h"
70 #include "sdp-client.h"
71 #include "attrib/gatt.h"
75 #include "attrib-server.h"
78 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
80 #ifdef TIZEN_FEATURE_BLUEZ_BATTERY_WATCH
81 #include <sys/ioctl.h>
82 #endif /* TIZEN_FEATURE_BLUEZ_BATTERY_WATCH */
85 #define DISCONNECT_TIMER 2
86 #define DISCOVERY_TIMER 1
87 #define INVALID_FLAGS 0xff
90 #define MIN(a, b) ((a) < (b) ? (a) : (b))
93 #define RSSI_THRESHOLD 8
95 #define GATT_PRIM_SVC_UUID_STR "2800"
96 #define GATT_SND_SVC_UUID_STR "2801"
97 #define GATT_INCLUDE_UUID_STR "2802"
98 #define GATT_CHARAC_UUID_STR "2803"
100 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
101 #define DEV_MAX_MANUFACTURER_DATA_LEN 248
104 static DBusConnection *dbus_conn = NULL;
105 static unsigned service_state_cb_id;
107 struct btd_disconnect_data {
109 disconnect_watch watch;
111 GDestroyNotify destroy;
117 struct btd_device *device;
120 struct btd_adapter_pin_cb_iter *cb_iter;
123 struct timespec attempt_start_time;
124 long last_attempt_duration_ms;
131 AUTH_TYPE_NOTIFY_PASSKEY,
132 AUTH_TYPE_NOTIFY_PINCODE,
135 struct authentication_req {
138 struct btd_device *device;
152 struct btd_device *device;
155 GSList *profiles_added;
158 int reconnect_attempt;
163 struct included_search {
164 struct browse_req *req;
169 struct svc_callback {
172 struct btd_device *dev;
173 device_svc_cb_t func;
177 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
178 struct le_adv_report_info {
180 char manufacturer_data[DEV_MAX_MANUFACTURER_DATA_LEN];
181 uint8_t manufacturer_data_len;
185 /* Per-bearer (LE or BR/EDR) device state */
186 struct bearer_state {
198 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
201 DEV_PAIRED_BREDR = 1,
207 DEV_CONNECTED_NONE = 0,
208 DEV_CONNECTED_BREDR = 1,
210 DEV_CONNECTED_BREDR_LE,
211 } dev_connected_state;
213 struct trusted_profile_t {
225 bdaddr_t conn_bdaddr;
226 uint8_t conn_bdaddr_type;
232 bool pending_paired; /* "Paired" waiting for SDP */
234 GSList *svc_callbacks;
238 char name[MAX_NAME_LENGTH + 1];
247 struct btd_adapter *adapter;
249 GSList *primaries; /* List of primary services */
250 GSList *services; /* List of btd_service */
251 GSList *pending; /* Pending services */
252 GSList *watches; /* List of disconnect_data */
257 struct browse_req *browse; /* service discover request */
258 struct bonding_req *bonding;
259 struct authentication_req *authr; /* authentication request */
260 GSList *disconnects; /* disconnects message */
261 DBusMessage *connect; /* connect message */
262 DBusMessage *disconnect; /* disconnect message */
265 struct bt_att *att; /* The new ATT transport */
266 uint16_t att_mtu; /* The ATT MTU */
267 unsigned int att_disconn_id;
270 * TODO: For now, device creates and owns the client-role gatt_db, but
271 * this needs to be persisted in a more central place so that proper
272 * attribute cache support can be built.
274 struct gatt_db *db; /* GATT db cache */
276 struct bt_gatt_client *client; /* GATT client instance */
277 struct bt_gatt_server *server; /* GATT server instance */
278 unsigned int gatt_ready_id;
280 struct btd_gatt_client *client_dbus;
282 struct bearer_state bredr_state;
283 struct bearer_state le_state;
285 struct csrk_info *local_csrk;
286 struct csrk_info *remote_csrk;
287 uint8_t ltk_enc_size;
289 sdp_list_t *tmp_records;
295 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
296 struct trusted_profile_t trusted_profiles;
299 gboolean auto_connect;
300 gboolean disable_auto_connect;
301 gboolean general_connect;
309 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
311 char *manufacturer_data;
312 int manufacturer_data_len;
313 struct le_adv_report_info le_adv_data;
314 int remote_feature_flags;
316 gboolean gatt_connected;
317 uint16_t auth_payload_timeout;
319 uint8_t last_bdaddr_type;
320 uint8_t auth_bdaddr_type;
321 gboolean ipsp_connected; /* IPSP Connection state */
322 char if_name[16 + 1]; /* BT interface UP after IPSP connection */
323 uint8_t rpa_res_support; /* RPA Resolution capability of device */
324 uint16_t max_tx_octets;
325 uint16_t max_tx_time;
326 uint16_t max_rx_octets;
327 uint16_t max_rx_time;
329 DBusMessage *req_att_mtu; /* Attribute MTU request message */
331 bool pending_conn_update;
336 static const uint16_t uuid_list[] = {
343 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
345 SHOW_AUTHORIZATION = 0x0, /* 0b00 */
346 SUPPORTED_BLOCKED = 0x1, /* 0b01 */
347 SUPPORTED_TRUSTED= 0x2, /* 0b10 */
348 } bt_profile_trusted_states;
350 #define PBAP_SHIFT_OFFSET 0
351 #define MAP_SHIFT_OFFSET 2
352 #define SAP_SHIFT_OFFSET 4
353 #define HFP_HS_SHIFT_OFFSET 6
354 #define A2DP_SHIFT_OFFSET 8
356 #define PROFILE_SUPPORTED 0x3 /* This corresponds to binary 0b11*/
360 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
361 #define OTP_PSM 0x0025
364 #define BT_OTC_SERVICE_NAME "org.otp.client"
365 #define BT_OTC_OBJECT_PATH "/org/otp/client"
366 #define BT_OTC_INTERFACE_NAME "org.otp.otc_channel"
369 #define BT_OTS_SERVICE_NAME "org.projectx.otp"
370 #define BT_OTS_OBJECT_PATH "/org/projectx/otp"
371 #define BT_OTS_INTERFACE_NAME "org.projectx.otp_service"
374 BT_OTP_CLIENT_ROLE = 0x00,
378 struct otc_conn_info {
379 const char *dev_path;
385 GSList *otc_connection_list = NULL;
388 static int device_browse_gatt(struct btd_device *device, DBusMessage *msg);
389 static int device_browse_sdp(struct btd_device *device, DBusMessage *msg);
391 static struct bearer_state *get_state(struct btd_device *dev,
394 if (bdaddr_type == BDADDR_BREDR)
395 return &dev->bredr_state;
397 return &dev->le_state;
400 static GSList *find_service_with_profile(GSList *list, struct btd_profile *p)
404 for (l = list; l != NULL; l = g_slist_next(l)) {
405 struct btd_service *service = l->data;
407 if (btd_service_get_profile(service) == p)
414 static GSList *find_service_with_state(GSList *list,
415 btd_service_state_t state)
419 for (l = list; l != NULL; l = g_slist_next(l)) {
420 struct btd_service *service = l->data;
422 if (btd_service_get_state(service) == state)
429 static GSList *find_service_with_uuid(GSList *list, char *uuid)
433 for (l = list; l != NULL; l = g_slist_next(l)) {
434 struct btd_service *service = l->data;
435 struct btd_profile *profile = btd_service_get_profile(service);
437 if (bt_uuid_strcmp(profile->remote_uuid, uuid) == 0)
444 static void update_technologies(GKeyFile *file, struct btd_device *dev)
450 list[len++] = "BR/EDR";
455 if (dev->bdaddr_type == BDADDR_LE_PUBLIC)
460 g_key_file_set_string(file, "General", "AddressType", type);
465 g_key_file_set_string_list(file, "General", "SupportedTechnologies",
469 static void store_csrk(struct csrk_info *csrk, GKeyFile *key_file,
475 for (i = 0; i < 16; i++)
476 sprintf(key + (i * 2), "%2.2X", csrk->key[i]);
478 g_key_file_set_string(key_file, group, "Key", key);
479 g_key_file_set_integer(key_file, group, "Counter", csrk->counter);
482 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
483 static char *manufacturer_data2str(char *data, int size)
485 char str[DEV_MAX_MANUFACTURER_DATA_LEN * 3 + 1];
490 for(i = 0; i < size; i++) {
491 snprintf(tmp, sizeof(tmp), "%d ", data[i]);
492 g_strlcat(str, tmp, sizeof(str));
495 return g_strdup(str);
498 static void load_manufacturer_data_2digit(char *data, int len, char *buf)
503 split = g_strsplit(data, " ", 0);
505 for (i = 0; i < len; i++) {
506 if (split[i] == NULL)
509 buf[i] = (char)g_ascii_strtoull(split[i], NULL, 10);
518 static gboolean store_device_info_cb(gpointer user_data)
520 struct btd_device *device = user_data;
522 char filename[PATH_MAX];
523 char device_addr[18];
528 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
529 gboolean svc_change_regd = false;
532 device->store_id = 0;
534 ba2str(&device->bdaddr, device_addr);
536 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
538 ba2str(device->rpa, device_addr);
540 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
541 btd_adapter_get_storage_dir(device->adapter),
544 key_file = g_key_file_new();
545 g_key_file_load_from_file(key_file, filename, 0, NULL);
547 g_key_file_set_string(key_file, "General", "Name", device->name);
549 if (device->alias != NULL)
550 g_key_file_set_string(key_file, "General", "Alias",
553 g_key_file_remove_key(key_file, "General", "Alias", NULL);
556 sprintf(class, "0x%6.6x", device->class);
557 g_key_file_set_string(key_file, "General", "Class", class);
559 g_key_file_remove_key(key_file, "General", "Class", NULL);
562 if (device->appearance) {
563 sprintf(class, "0x%4.4x", device->appearance);
564 g_key_file_set_string(key_file, "General", "Appearance", class);
566 g_key_file_remove_key(key_file, "General", "Appearance", NULL);
569 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
570 if (device->rpa_res_support) {
571 g_key_file_set_integer(key_file, "General", "RPAResSupport",
572 device->rpa_res_support);
574 g_key_file_remove_key(key_file, "General", "RPAResSupport", NULL);
578 update_technologies(key_file, device);
580 g_key_file_set_boolean(key_file, "General", "Trusted",
582 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
583 struct trusted_profile_t trust_profile = device->trusted_profiles;
584 int trusted_profiles = (trust_profile.pbap << PBAP_SHIFT_OFFSET) |
585 (trust_profile.map << MAP_SHIFT_OFFSET) |
586 (trust_profile.sap << SAP_SHIFT_OFFSET) |
587 (trust_profile.hfp_hs << HFP_HS_SHIFT_OFFSET) |
588 (trust_profile.a2dp << A2DP_SHIFT_OFFSET);
589 DBG("Storing TrustedProfiles %d", trusted_profiles);
590 g_key_file_set_integer(key_file, "General", "TrustedProfiles",
593 g_key_file_set_boolean(key_file, "General", "Blocked",
600 uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
601 for (i = 0, l = device->uuids; l; l = g_slist_next(l), i++)
603 g_key_file_set_string_list(key_file, "General", "Services",
604 (const char **)uuids, i);
606 g_key_file_remove_key(key_file, "General", "Services", NULL);
609 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
610 if (device->le_adv_data.flags) {
611 g_key_file_set_integer(key_file, "General", "Flags",
612 device->le_adv_data.flags);
614 g_key_file_remove_key(key_file, "General", "Flags", NULL);
617 if (device->manufacturer_data) {
618 str = manufacturer_data2str(device->manufacturer_data,
619 device->manufacturer_data_len);
620 g_key_file_set_string(key_file, "General",
621 "LegacyManufacturerData",
624 g_key_file_set_integer(key_file, "General",
625 "LegacyManufacturerDataLen",
626 device->manufacturer_data_len);
628 g_key_file_remove_key(key_file, "General",
629 "LegacyManufacturerData", NULL);
630 g_key_file_remove_key(key_file, "General",
631 "LegacyManufacturerDataLen", NULL);
637 ba2str(&device->bdaddr, irk_addr);
638 g_key_file_set_string(key_file, "General", "IdentityAddress",
641 g_key_file_remove_key(key_file, "General", "IdentityAddress",
646 if (device->vendor_src) {
647 g_key_file_set_integer(key_file, "DeviceID", "Source",
649 g_key_file_set_integer(key_file, "DeviceID", "Vendor",
651 g_key_file_set_integer(key_file, "DeviceID", "Product",
653 g_key_file_set_integer(key_file, "DeviceID", "Version",
656 g_key_file_remove_group(key_file, "DeviceID", NULL);
659 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
660 svc_change_regd = bt_att_get_svc_changed_indication_registered(device->att);
661 g_key_file_set_boolean(key_file, "Att", "SvcChangeRegd",
665 if (device->local_csrk)
666 store_csrk(device->local_csrk, key_file, "LocalSignatureKey");
668 if (device->remote_csrk)
669 store_csrk(device->remote_csrk, key_file, "RemoteSignatureKey");
671 create_file(filename, S_IRUSR | S_IWUSR);
673 str = g_key_file_to_data(key_file, &length, NULL);
674 g_file_set_contents(filename, str, length, NULL);
677 g_key_file_free(key_file);
683 static bool device_address_is_private(struct btd_device *dev)
685 if (dev->bdaddr_type != BDADDR_LE_RANDOM)
688 switch (dev->bdaddr.b[5] >> 6) {
689 case 0x00: /* Private non-resolvable */
690 case 0x01: /* Private resolvable */
697 static void store_device_info(struct btd_device *device)
699 if (device->temporary || device->store_id > 0)
702 if (device_address_is_private(device)) {
703 DBG("Can't store info for private addressed device %s",
708 device->store_id = g_idle_add(store_device_info_cb, device);
711 void device_store_cached_name(struct btd_device *dev, const char *name)
713 char filename[PATH_MAX];
719 if (device_address_is_private(dev)) {
720 DBG("Can't store name for private addressed device %s",
725 ba2str(&dev->bdaddr, d_addr);
727 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
729 ba2str(dev->rpa, d_addr);
732 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
733 btd_adapter_get_storage_dir(dev->adapter), d_addr);
734 create_file(filename, S_IRUSR | S_IWUSR);
736 key_file = g_key_file_new();
737 g_key_file_load_from_file(key_file, filename, 0, NULL);
738 g_key_file_set_string(key_file, "General", "Name", name);
740 data = g_key_file_to_data(key_file, &length, NULL);
741 g_file_set_contents(filename, data, length, NULL);
744 g_key_file_free(key_file);
747 static void browse_request_free(struct browse_req *req)
749 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
752 struct btd_device *device = req->device;
754 if (device->browse == req)
755 device->browse = NULL;
757 if (req->listener_id)
758 g_dbus_remove_watch(dbus_conn, req->listener_id);
760 dbus_message_unref(req->msg);
761 g_slist_free_full(req->profiles_added, g_free);
763 sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
768 static bool gatt_cache_is_enabled(struct btd_device *device)
770 switch (main_opts.gatt_cache) {
771 case BT_GATT_CACHE_YES:
772 return device_is_paired(device, device->bdaddr_type);
773 case BT_GATT_CACHE_NO:
775 case BT_GATT_CACHE_ALWAYS:
781 static void gatt_cache_cleanup(struct btd_device *device)
783 if (gatt_cache_is_enabled(device))
786 gatt_db_clear(device->db);
789 static void gatt_client_cleanup(struct btd_device *device)
794 gatt_cache_cleanup(device);
795 bt_gatt_client_set_service_changed(device->client, NULL, NULL, NULL);
797 if (device->gatt_ready_id > 0) {
798 bt_gatt_client_ready_unregister(device->client,
799 device->gatt_ready_id);
800 device->gatt_ready_id = 0;
803 bt_gatt_client_unref(device->client);
804 device->client = NULL;
807 static void gatt_server_cleanup(struct btd_device *device)
812 btd_gatt_database_att_disconnected(
813 btd_adapter_get_database(device->adapter), device);
815 bt_gatt_server_unref(device->server);
816 device->server = NULL;
819 static void attio_cleanup(struct btd_device *device)
821 if (device->att_disconn_id)
822 bt_att_unregister_disconnect(device->att,
823 device->att_disconn_id);
825 if (device->att_io) {
826 g_io_channel_shutdown(device->att_io, FALSE, NULL);
827 g_io_channel_unref(device->att_io);
828 device->att_io = NULL;
831 gatt_client_cleanup(device);
832 gatt_server_cleanup(device);
835 bt_att_unref(device->att);
839 if (device->attrib) {
840 GAttrib *attrib = device->attrib;
842 device->attrib = NULL;
843 g_attrib_cancel_all(attrib);
844 g_attrib_unref(attrib);
848 static void browse_request_cancel(struct browse_req *req)
850 struct btd_device *device = req->device;
851 struct btd_adapter *adapter = device->adapter;
855 bt_cancel_discovery(btd_adapter_get_address(adapter), &device->bdaddr);
857 attio_cleanup(device);
859 browse_request_free(req);
862 static void svc_dev_remove(gpointer user_data)
864 struct svc_callback *cb = user_data;
867 g_source_remove(cb->idle_id);
869 cb->func(cb->dev, -ENODEV, cb->user_data);
874 static void device_free(gpointer user_data)
876 struct btd_device *device = user_data;
878 btd_gatt_client_destroy(device->client_dbus);
879 device->client_dbus = NULL;
881 g_slist_free_full(device->uuids, g_free);
882 g_slist_free_full(device->primaries, g_free);
883 g_slist_free_full(device->svc_callbacks, svc_dev_remove);
885 /* Reset callbacks since the device is going to be freed */
886 gatt_db_unregister(device->db, device->db_id);
888 attio_cleanup(device);
890 gatt_db_unref(device->db);
892 bt_ad_unref(device->ad);
894 if (device->tmp_records)
895 sdp_list_free(device->tmp_records,
896 (sdp_free_func_t) sdp_record_free);
898 if (device->disconn_timer)
899 g_source_remove(device->disconn_timer);
901 if (device->discov_timer)
902 g_source_remove(device->discov_timer);
905 dbus_message_unref(device->connect);
907 if (device->disconnect)
908 dbus_message_unref(device->disconnect);
913 if (device->authr->agent)
914 agent_unref(device->authr->agent);
915 g_free(device->authr->pincode);
916 g_free(device->authr);
919 if (device->eir_uuids)
920 g_slist_free_full(device->eir_uuids, g_free);
922 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
925 g_free(device->local_csrk);
926 g_free(device->remote_csrk);
927 g_free(device->path);
928 g_free(device->alias);
929 free(device->modalias);
933 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
934 void device_set_remote_feature_flag(struct btd_device *device, int flags)
936 device->remote_feature_flags = flags;
939 gboolean device_is_bredrle(struct btd_device *device)
941 return (device->remote_feature_flags & (EIR_CONTROLLER | EIR_SIM_HOST));
945 bool device_is_paired(struct btd_device *device, uint8_t bdaddr_type)
947 struct bearer_state *state = get_state(device, bdaddr_type);
949 return state->paired;
952 bool device_is_bonded(struct btd_device *device, uint8_t bdaddr_type)
954 struct bearer_state *state = get_state(device, bdaddr_type);
956 return state->bonded;
959 gboolean device_is_trusted(struct btd_device *device)
961 return device->trusted;
964 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
965 gboolean device_is_profile_trusted(struct btd_device *device,
968 if (g_strcmp0(uuid, OBEX_PSE_UUID) == 0) {
969 if (device->trusted_profiles.pbap == SUPPORTED_TRUSTED)
971 } else if (g_strcmp0(uuid, OBEX_MAS_UUID) == 0) {
972 if (device->trusted_profiles.map == SUPPORTED_TRUSTED)
974 } else if (g_strcmp0(uuid, SAP_UUID) == 0) {
975 if (device->trusted_profiles.sap == SUPPORTED_TRUSTED)
977 } else if (g_strcmp0(uuid, HFP_HS_UUID) == 0) {
978 if (device->trusted_profiles.hfp_hs == SUPPORTED_TRUSTED)
980 } else if (g_strcmp0(uuid, A2DP_SINK_UUID) == 0) {
981 if (device->trusted_profiles.a2dp == SUPPORTED_TRUSTED)
987 gboolean device_is_profile_blocked(struct btd_device *device,
990 if (g_strcmp0(uuid, OBEX_PSE_UUID) == 0) {
991 if (device->trusted_profiles.pbap == SUPPORTED_BLOCKED)
993 } else if (g_strcmp0(uuid, OBEX_MAS_UUID) == 0) {
994 if (device->trusted_profiles.map == SUPPORTED_BLOCKED)
996 } else if (g_strcmp0(uuid, SAP_UUID) == 0) {
997 if (device->trusted_profiles.sap == SUPPORTED_BLOCKED)
999 } else if (g_strcmp0(uuid, HFP_HS_UUID) == 0) {
1000 if (device->trusted_profiles.hfp_hs == SUPPORTED_BLOCKED)
1002 } else if (g_strcmp0(uuid, A2DP_SINK_UUID) == 0) {
1003 if (device->trusted_profiles.a2dp == SUPPORTED_BLOCKED)
1010 static gboolean dev_property_get_address(const GDBusPropertyTable *property,
1011 DBusMessageIter *iter, void *data)
1013 struct btd_device *device = data;
1015 const char *ptr = dstaddr;
1017 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1019 ba2str(device->rpa, dstaddr);
1022 ba2str(&device->bdaddr, dstaddr);
1023 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
1028 static gboolean property_get_address_type(const GDBusPropertyTable *property,
1029 DBusMessageIter *iter, void *user_data)
1031 struct btd_device *device = user_data;
1034 if (device->le && device->bdaddr_type == BDADDR_LE_RANDOM)
1039 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
1044 static gboolean dev_property_get_name(const GDBusPropertyTable *property,
1045 DBusMessageIter *iter, void *data)
1047 struct btd_device *device = data;
1048 const char *ptr = device->name;
1050 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
1055 static gboolean dev_property_exists_name(const GDBusPropertyTable *property,
1058 struct btd_device *dev = data;
1060 return device_name_known(dev);
1063 static gboolean dev_property_get_alias(const GDBusPropertyTable *property,
1064 DBusMessageIter *iter, void *data)
1066 struct btd_device *device = data;
1070 /* Alias (fallback to name or address) */
1071 if (device->alias != NULL)
1072 ptr = device->alias;
1073 else if (strlen(device->name) > 0) {
1076 ba2str(&device->bdaddr, dstaddr);
1077 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
1078 g_strdelimit(dstaddr, ":", '-');
1083 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
1088 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1089 static gboolean dev_property_get_alias_set(const GDBusPropertyTable *property,
1090 DBusMessageIter *iter, void *data)
1092 struct btd_device *device = data;
1095 if (device->alias != NULL)
1100 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1106 static void set_alias(GDBusPendingPropertySet id, const char *alias,
1109 struct btd_device *device = data;
1112 if ((device->alias == NULL && g_str_equal(alias, "")) ||
1113 g_strcmp0(device->alias, alias) == 0) {
1114 g_dbus_pending_property_success(id);
1118 g_free(device->alias);
1119 device->alias = g_str_equal(alias, "") ? NULL : g_strdup(alias);
1121 store_device_info(device);
1123 g_dbus_emit_property_changed(dbus_conn, device->path,
1124 DEVICE_INTERFACE, "Alias");
1126 g_dbus_pending_property_success(id);
1129 static void dev_property_set_alias(const GDBusPropertyTable *property,
1130 DBusMessageIter *value,
1131 GDBusPendingPropertySet id, void *data)
1135 if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_STRING) {
1136 g_dbus_pending_property_error(id,
1137 ERROR_INTERFACE ".InvalidArguments",
1138 "Invalid arguments in method call");
1142 dbus_message_iter_get_basic(value, &alias);
1144 set_alias(id, alias, data);
1147 static gboolean dev_property_exists_class(const GDBusPropertyTable *property,
1150 struct btd_device *device = data;
1152 return device->class != 0;
1155 static gboolean dev_property_get_class(const GDBusPropertyTable *property,
1156 DBusMessageIter *iter, void *data)
1158 struct btd_device *device = data;
1160 if (device->class == 0)
1163 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &device->class);
1168 static gboolean get_appearance(const GDBusPropertyTable *property, void *data,
1169 uint16_t *appearance)
1171 struct btd_device *device = data;
1173 if (dev_property_exists_class(property, data))
1176 if (device->appearance) {
1177 *appearance = device->appearance;
1184 static gboolean dev_property_exists_appearance(
1185 const GDBusPropertyTable *property, void *data)
1187 uint16_t appearance;
1189 return get_appearance(property, data, &appearance);
1192 static gboolean dev_property_get_appearance(const GDBusPropertyTable *property,
1193 DBusMessageIter *iter, void *data)
1195 uint16_t appearance;
1197 if (!get_appearance(property, data, &appearance))
1200 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &appearance);
1205 static const char *get_icon(const GDBusPropertyTable *property, void *data)
1207 struct btd_device *device = data;
1208 const char *icon = NULL;
1209 uint16_t appearance;
1211 if (device->class != 0)
1212 icon = class_to_icon(device->class);
1213 else if (get_appearance(property, data, &appearance))
1214 icon = gap_appearance_to_icon(appearance);
1219 static gboolean dev_property_exists_icon(
1220 const GDBusPropertyTable *property, void *data)
1222 return get_icon(property, data) != NULL;
1225 static gboolean dev_property_get_icon(const GDBusPropertyTable *property,
1226 DBusMessageIter *iter, void *data)
1230 icon = get_icon(property, data);
1234 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &icon);
1239 static gboolean dev_property_get_paired(const GDBusPropertyTable *property,
1240 DBusMessageIter *iter, void *data)
1242 struct btd_device *dev = data;
1245 if (dev->bredr_state.paired || dev->le_state.paired)
1250 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1255 static gboolean dev_property_get_legacy(const GDBusPropertyTable *property,
1256 DBusMessageIter *iter, void *data)
1258 struct btd_device *device = data;
1259 dbus_bool_t val = device->legacy;
1261 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1266 static gboolean dev_property_get_rssi(const GDBusPropertyTable *property,
1267 DBusMessageIter *iter, void *data)
1269 struct btd_device *dev = data;
1270 dbus_int16_t val = dev->rssi;
1272 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &val);
1277 static gboolean dev_property_exists_rssi(const GDBusPropertyTable *property,
1280 struct btd_device *dev = data;
1288 static gboolean dev_property_get_tx_power(const GDBusPropertyTable *property,
1289 DBusMessageIter *iter, void *data)
1291 struct btd_device *dev = data;
1292 dbus_int16_t val = dev->tx_power;
1294 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &val);
1299 static gboolean dev_property_exists_tx_power(const GDBusPropertyTable *property,
1302 struct btd_device *dev = data;
1304 if (dev->tx_power == 127)
1311 dev_property_get_svc_resolved(const GDBusPropertyTable *property,
1312 DBusMessageIter *iter, void *data)
1314 struct btd_device *device = data;
1315 gboolean val = device->svc_refreshed;
1317 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1322 static gboolean dev_property_flags_exist(const GDBusPropertyTable *property,
1325 struct btd_device *device = data;
1327 return device->ad_flags[0] != INVALID_FLAGS;
1331 dev_property_get_flags(const GDBusPropertyTable *property,
1332 DBusMessageIter *iter, void *data)
1334 struct btd_device *device = data;
1335 uint8_t *flags = device->ad_flags;
1336 DBusMessageIter array;
1338 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1339 DBUS_TYPE_BYTE_AS_STRING, &array);
1340 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
1341 &flags, sizeof(device->ad_flags));
1342 dbus_message_iter_close_container(iter, &array);
1347 static gboolean dev_property_get_trusted(const GDBusPropertyTable *property,
1348 DBusMessageIter *iter, void *data)
1350 struct btd_device *device = data;
1351 gboolean val = device_is_trusted(device);
1353 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1358 static void set_trust(GDBusPendingPropertySet id, gboolean value, void *data)
1360 struct btd_device *device = data;
1362 btd_device_set_trusted(device, value);
1364 g_dbus_pending_property_success(id);
1367 static void dev_property_set_trusted(const GDBusPropertyTable *property,
1368 DBusMessageIter *value,
1369 GDBusPendingPropertySet id, void *data)
1373 if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
1374 g_dbus_pending_property_error(id,
1375 ERROR_INTERFACE ".InvalidArguments",
1376 "Invalid arguments in method call");
1380 dbus_message_iter_get_basic(value, &b);
1382 set_trust(id, b, data);
1385 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1386 static gboolean dev_property_get_trusted_profiles(const GDBusPropertyTable *property,
1387 DBusMessageIter *iter, void *data)
1389 struct btd_device *device = data;
1390 uint32_t pbap = device->trusted_profiles.pbap;
1391 uint32_t map = device->trusted_profiles.map;
1392 uint32_t sap = device->trusted_profiles.sap;
1393 uint32_t hfp_hs = device->trusted_profiles.hfp_hs;
1394 uint32_t a2dp = device->trusted_profiles.a2dp;
1396 unsigned int val = (pbap << PBAP_SHIFT_OFFSET) |
1397 (map << MAP_SHIFT_OFFSET) |
1398 (sap << SAP_SHIFT_OFFSET) |
1399 (hfp_hs << HFP_HS_SHIFT_OFFSET) |
1400 (a2dp << A2DP_SHIFT_OFFSET);
1402 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &val);
1408 static gboolean dev_property_get_blocked(const GDBusPropertyTable *property,
1409 DBusMessageIter *iter, void *data)
1411 struct btd_device *device = data;
1413 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
1419 static void set_blocked(GDBusPendingPropertySet id, gboolean value, void *data)
1421 struct btd_device *device = data;
1425 err = device_block(device, FALSE);
1427 err = device_unblock(device, FALSE, FALSE);
1431 g_dbus_pending_property_success(id);
1434 g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed",
1435 "Kernel lacks blacklist support");
1438 g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed",
1445 static void dev_property_set_blocked(const GDBusPropertyTable *property,
1446 DBusMessageIter *value,
1447 GDBusPendingPropertySet id, void *data)
1451 if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
1452 g_dbus_pending_property_error(id,
1453 ERROR_INTERFACE ".InvalidArguments",
1454 "Invalid arguments in method call");
1458 dbus_message_iter_get_basic(value, &b);
1460 set_blocked(id, b, data);
1463 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1464 static uint8_t device_get_connected_state(struct btd_device *device)
1466 if (device->bredr_state.connected && device->le_state.connected)
1467 return DEV_CONNECTED_BREDR_LE;
1468 else if (device->bredr_state.connected)
1469 return DEV_CONNECTED_BREDR;
1470 else if (device->le_state.connected)
1471 return DEV_CONNECTED_LE;
1473 return DEV_CONNECTED_NONE;
1476 static gboolean dev_property_get_payload(const GDBusPropertyTable *property,
1477 DBusMessageIter *iter, void *data)
1479 struct btd_device *dev = data;
1480 dbus_uint16_t payload_timeout = dev->auth_payload_timeout;
1482 dbus_message_iter_append_basic(iter,
1483 DBUS_TYPE_UINT16, &payload_timeout);
1488 static gboolean dev_property_get_last_addr_type(const GDBusPropertyTable *property,
1489 DBusMessageIter *iter, void *data)
1491 struct btd_device *dev = data;
1492 uint8_t last_addr_type = dev->last_bdaddr_type;
1494 dbus_message_iter_append_basic(iter,
1495 DBUS_TYPE_BYTE, &last_addr_type);
1500 static gboolean dev_property_get_att_mtu(const GDBusPropertyTable *property,
1501 DBusMessageIter *iter, void *data)
1503 struct btd_device *device = data;
1504 dbus_uint16_t mtu = bt_gatt_client_get_mtu(device->client);
1506 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &mtu);
1511 static gboolean dev_property_get_gatt_connected(const GDBusPropertyTable *property,
1512 DBusMessageIter *iter, void *data)
1514 struct btd_device *device = data;
1515 dbus_bool_t gatt_connected;
1517 if (device->gatt_connected)
1518 gatt_connected = TRUE;
1520 gatt_connected = FALSE;
1522 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
1528 static gboolean dev_property_get_ipsp_conn_state(const GDBusPropertyTable *property,
1529 DBusMessageIter *iter, void *data)
1531 struct btd_device *dev = data;
1532 dbus_bool_t ipsp_connected;
1534 if (dev->ipsp_connected)
1535 ipsp_connected = TRUE;
1537 ipsp_connected = FALSE;
1539 dbus_message_iter_append_basic(iter,
1540 DBUS_TYPE_BOOLEAN, &ipsp_connected);
1545 static gboolean dev_property_get_ipsp_conn_bt_iface_name(const GDBusPropertyTable *property,
1546 DBusMessageIter *iter, void *data)
1548 struct btd_device *dev = data;
1549 char *ptr = g_strdup(dev->if_name);
1551 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, (const char **)&ptr);
1559 static gboolean dev_property_get_connected(const GDBusPropertyTable *property,
1560 DBusMessageIter *iter, void *data)
1562 struct btd_device *dev = data;
1564 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1565 uint8_t connected = device_get_connected_state(dev);
1567 dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &connected);
1569 dbus_bool_t connected;
1571 if (dev->bredr_state.connected || dev->le_state.connected)
1576 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &connected);
1582 static gboolean dev_property_get_uuids(const GDBusPropertyTable *property,
1583 DBusMessageIter *iter, void *data)
1585 struct btd_device *dev = data;
1586 DBusMessageIter entry;
1589 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1590 DBUS_TYPE_STRING_AS_STRING, &entry);
1592 if (dev->bredr_state.svc_resolved || dev->le_state.svc_resolved)
1594 else if (dev->eir_uuids)
1599 for (; l != NULL; l = l->next)
1600 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
1603 dbus_message_iter_close_container(iter, &entry);
1608 static gboolean dev_property_get_modalias(const GDBusPropertyTable *property,
1609 DBusMessageIter *iter, void *data)
1611 struct btd_device *device = data;
1613 if (!device->modalias)
1616 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1622 static gboolean dev_property_exists_modalias(const GDBusPropertyTable *property,
1625 struct btd_device *device = data;
1627 return device->modalias ? TRUE : FALSE;
1630 static gboolean dev_property_get_adapter(const GDBusPropertyTable *property,
1631 DBusMessageIter *iter, void *data)
1633 struct btd_device *device = data;
1634 const char *str = adapter_get_path(device->adapter);
1636 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &str);
1641 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1642 static gboolean property_get_manufacturer_data_len(const GDBusPropertyTable *property,
1643 DBusMessageIter *iter, void *user_data)
1645 struct btd_device *device = user_data;
1646 dbus_uint16_t val = device->manufacturer_data_len;
1648 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &val);
1653 static gboolean property_get_manufacturer_data(const GDBusPropertyTable *property,
1654 DBusMessageIter *iter, void *user_data)
1656 struct btd_device *device = user_data;
1657 char str[DEV_MAX_MANUFACTURER_DATA_LEN] = {0};
1658 DBusMessageIter array;
1660 memset(str, 0, DEV_MAX_MANUFACTURER_DATA_LEN);
1661 if (device->manufacturer_data_len)
1662 memcpy(str, device->manufacturer_data,
1663 device->manufacturer_data_len);
1665 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1666 DBUS_TYPE_BYTE_AS_STRING, &array);
1668 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
1669 &device->manufacturer_data,
1670 device->manufacturer_data_len);
1672 dbus_message_iter_close_container(iter, &array);
1677 gboolean device_get_gatt_connected(const struct btd_device *device)
1679 return device->gatt_connected;
1683 static void append_manufacturer_data(void *data, void *user_data)
1685 struct bt_ad_manufacturer_data *md = data;
1686 DBusMessageIter *dict = user_data;
1688 g_dbus_dict_append_basic_array(dict,
1689 DBUS_TYPE_UINT16, &md->manufacturer_id,
1690 DBUS_TYPE_BYTE, &md->data, md->len);
1694 dev_property_get_manufacturer_data(const GDBusPropertyTable *property,
1695 DBusMessageIter *iter, void *data)
1697 struct btd_device *device = data;
1698 DBusMessageIter dict;
1700 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1701 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1702 DBUS_TYPE_UINT16_AS_STRING
1703 DBUS_TYPE_VARIANT_AS_STRING
1704 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1707 bt_ad_foreach_manufacturer_data(device->ad, append_manufacturer_data,
1710 dbus_message_iter_close_container(iter, &dict);
1716 dev_property_manufacturer_data_exist(const GDBusPropertyTable *property,
1719 struct btd_device *device = data;
1721 return bt_ad_has_manufacturer_data(device->ad, NULL);
1724 static void append_service_data(void *data, void *user_data)
1726 struct bt_ad_service_data *sd = data;
1727 DBusMessageIter *dict = user_data;
1728 char uuid_str[MAX_LEN_UUID_STR];
1730 bt_uuid_to_string(&sd->uuid, uuid_str, sizeof(uuid_str));
1732 dict_append_array(dict, uuid_str, DBUS_TYPE_BYTE, &sd->data, sd->len);
1736 dev_property_get_service_data(const GDBusPropertyTable *property,
1737 DBusMessageIter *iter, void *data)
1739 struct btd_device *device = data;
1740 DBusMessageIter dict;
1742 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1743 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1744 DBUS_TYPE_STRING_AS_STRING
1745 DBUS_TYPE_VARIANT_AS_STRING
1746 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1749 bt_ad_foreach_service_data(device->ad, append_service_data, &dict);
1751 dbus_message_iter_close_container(iter, &dict);
1757 dev_property_service_data_exist(const GDBusPropertyTable *property,
1760 struct btd_device *device = data;
1762 return bt_ad_has_service_data(device->ad, NULL);
1765 static void append_advertising_data(void *data, void *user_data)
1767 struct bt_ad_data *ad = data;
1768 DBusMessageIter *dict = user_data;
1770 g_dbus_dict_append_basic_array(dict,
1771 DBUS_TYPE_BYTE, &ad->type,
1772 DBUS_TYPE_BYTE, &ad->data, ad->len);
1776 dev_property_get_advertising_data(const GDBusPropertyTable *property,
1777 DBusMessageIter *iter, void *data)
1779 struct btd_device *device = data;
1780 DBusMessageIter dict;
1782 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1783 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1784 DBUS_TYPE_BYTE_AS_STRING
1785 DBUS_TYPE_VARIANT_AS_STRING
1786 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1789 bt_ad_foreach_data(device->ad, append_advertising_data, &dict);
1791 dbus_message_iter_close_container(iter, &dict);
1797 dev_property_advertising_data_exist(const GDBusPropertyTable *property,
1800 struct btd_device *device = data;
1802 return bt_ad_has_data(device->ad, NULL);
1805 static gboolean disconnect_all(gpointer user_data)
1807 struct btd_device *device = user_data;
1809 device->disconn_timer = 0;
1811 if (device->bredr_state.connected)
1812 btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
1815 if (device->le_state.connected)
1816 btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
1817 device->bdaddr_type);
1822 int device_block(struct btd_device *device, gboolean update_only)
1826 if (device->blocked)
1829 if (device->disconn_timer > 0)
1830 g_source_remove(device->disconn_timer);
1832 disconnect_all(device);
1834 while (device->services != NULL) {
1835 struct btd_service *service = device->services->data;
1837 device->services = g_slist_remove(device->services, service);
1838 service_remove(service);
1843 err = btd_adapter_block_address(device->adapter,
1845 device->bdaddr_type);
1846 if (!err && device->bredr)
1847 err = btd_adapter_block_address(device->adapter,
1855 device->blocked = TRUE;
1857 store_device_info(device);
1859 btd_device_set_temporary(device, false);
1861 g_dbus_emit_property_changed(dbus_conn, device->path,
1862 DEVICE_INTERFACE, "Blocked");
1867 int device_unblock(struct btd_device *device, gboolean silent,
1868 gboolean update_only)
1872 if (!device->blocked)
1877 err = btd_adapter_unblock_address(device->adapter,
1879 device->bdaddr_type);
1880 if (!err && device->bredr)
1881 err = btd_adapter_unblock_address(device->adapter,
1889 device->blocked = FALSE;
1891 store_device_info(device);
1894 g_dbus_emit_property_changed(dbus_conn, device->path,
1895 DEVICE_INTERFACE, "Blocked");
1896 device_probe_profiles(device, device->uuids);
1902 static void browse_request_exit(DBusConnection *conn, void *user_data)
1904 struct browse_req *req = user_data;
1906 DBG("Requestor exited");
1908 browse_request_cancel(req);
1911 static void bonding_request_cancel(struct bonding_req *bonding)
1913 struct btd_device *device = bonding->device;
1914 struct btd_adapter *adapter = device->adapter;
1916 adapter_cancel_bonding(adapter, &device->bdaddr, device->bdaddr_type);
1919 static void dev_disconn_service(gpointer a, gpointer b)
1921 btd_service_disconnect(a);
1924 void device_request_disconnect(struct btd_device *device, DBusMessage *msg)
1926 if (device->bonding)
1927 bonding_request_cancel(device->bonding);
1930 browse_request_cancel(device->browse);
1932 if (device->att_io) {
1933 g_io_channel_shutdown(device->att_io, FALSE, NULL);
1934 g_io_channel_unref(device->att_io);
1935 device->att_io = NULL;
1938 if (device->connect) {
1939 DBusMessage *reply = btd_error_failed(device->connect,
1941 g_dbus_send_message(dbus_conn, reply);
1942 dbus_message_unref(device->connect);
1943 device->connect = NULL;
1946 if (btd_device_is_connected(device) && msg)
1947 device->disconnects = g_slist_append(device->disconnects,
1948 dbus_message_ref(msg));
1950 if (device->disconn_timer)
1953 g_slist_foreach(device->services, dev_disconn_service, NULL);
1955 g_slist_free(device->pending);
1956 device->pending = NULL;
1958 while (device->watches) {
1959 struct btd_disconnect_data *data = device->watches->data;
1962 /* temporary is set if device is going to be removed */
1963 data->watch(device, device->temporary,
1966 /* Check if the watch has been removed by callback function */
1967 if (!g_slist_find(device->watches, data))
1970 device->watches = g_slist_remove(device->watches, data);
1974 if (!btd_device_is_connected(device)) {
1976 g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
1980 device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER,
1985 bool device_is_disconnecting(struct btd_device *device)
1987 return device->disconn_timer > 0;
1990 void device_set_ltk_enc_size(struct btd_device *device, uint8_t enc_size)
1992 device->ltk_enc_size = enc_size;
1993 bt_att_set_enc_key_size(device->att, device->ltk_enc_size);
1996 static void device_set_auto_connect(struct btd_device *device, gboolean enable)
2000 if (!device || !device->le)
2003 ba2str(&device->bdaddr, addr);
2005 DBG("%s auto connect: %d", addr, enable);
2007 if (device->auto_connect == enable)
2010 device->auto_connect = enable;
2012 /* Disabling auto connect */
2013 if (enable == FALSE) {
2014 adapter_connect_list_remove(device->adapter, device);
2015 adapter_auto_connect_remove(device->adapter, device);
2019 /* Enabling auto connect */
2020 adapter_auto_connect_add(device->adapter, device);
2022 if (device->attrib) {
2023 DBG("Already connected");
2027 adapter_connect_list_add(device->adapter, device);
2030 static DBusMessage *dev_disconnect(DBusConnection *conn, DBusMessage *msg,
2033 struct btd_device *device = user_data;
2036 * If device is not trusted disable connections through passive
2037 * scanning until Device1.Connect is called
2039 if (device->auto_connect && !device->trusted) {
2040 device->disable_auto_connect = TRUE;
2041 device_set_auto_connect(device, FALSE);
2044 device_request_disconnect(device, msg);
2049 static int connect_next(struct btd_device *dev)
2051 struct btd_service *service;
2054 while (dev->pending) {
2055 service = dev->pending->data;
2057 err = btd_service_connect(service);
2061 dev->pending = g_slist_delete_link(dev->pending, dev->pending);
2067 static void device_profile_connected(struct btd_device *dev,
2068 struct btd_profile *profile, int err)
2070 struct btd_service *pending;
2073 DBG("%s %s (%d)", profile->name, strerror(-err), -err);
2076 btd_device_set_temporary(dev, false);
2078 if (dev->pending == NULL)
2081 if (!btd_device_is_connected(dev)) {
2083 case EHOSTDOWN: /* page timeout */
2084 case EHOSTUNREACH: /* adapter not powered */
2085 case ECONNABORTED: /* adapter powered down */
2090 pending = dev->pending->data;
2091 l = find_service_with_profile(dev->pending, profile);
2093 dev->pending = g_slist_delete_link(dev->pending, l);
2095 /* Only continue connecting the next profile if it matches the first
2096 * pending, otherwise it will trigger another connect to the same
2099 if (profile != btd_service_get_profile(pending))
2102 if (connect_next(dev) == 0)
2106 g_slist_free(dev->pending);
2107 dev->pending = NULL;
2112 if (!err && dbus_message_is_method_call(dev->connect, DEVICE_INTERFACE,
2114 dev->general_connect = TRUE;
2116 DBG("returning response to %s", dbus_message_get_sender(dev->connect));
2118 l = find_service_with_state(dev->services, BTD_SERVICE_STATE_CONNECTED);
2120 if (err && l == NULL) {
2121 /* Fallback to LE bearer if supported */
2122 if (err == -EHOSTDOWN && dev->le && !dev->le_state.connected) {
2123 err = device_connect_le(dev);
2128 g_dbus_send_message(dbus_conn,
2129 btd_error_failed(dev->connect, strerror(-err)));
2131 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2132 /* SDP is not required for Samsung TV Power on */
2133 if (g_strcmp0(profile->name, "hid-device") == 0) {
2134 DBG("Skip SDP discovery.");
2137 /* Start passive SDP discovery to update known services */
2138 if (dev->bredr && !dev->svc_refreshed)
2139 device_browse_sdp(dev, NULL);
2140 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2144 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2146 g_dbus_send_message(dbus_conn,
2147 btd_error_failed(dev->connect, strerror(-err)));
2149 g_dbus_send_reply(dbus_conn, dev->connect, DBUS_TYPE_INVALID);
2151 g_dbus_send_reply(dbus_conn, dev->connect, DBUS_TYPE_INVALID);
2155 dbus_message_unref(dev->connect);
2156 dev->connect = NULL;
2159 void device_add_eir_uuids(struct btd_device *dev, GSList *uuids)
2164 if (dev->bredr_state.svc_resolved || dev->le_state.svc_resolved)
2167 for (l = uuids; l != NULL; l = l->next) {
2168 const char *str = l->data;
2169 if (g_slist_find_custom(dev->eir_uuids, str, bt_uuid_strcmp))
2172 dev->eir_uuids = g_slist_append(dev->eir_uuids, g_strdup(str));
2176 g_dbus_emit_property_changed(dbus_conn, dev->path,
2177 DEVICE_INTERFACE, "UUIDs");
2180 static void add_manufacturer_data(void *data, void *user_data)
2182 struct eir_msd *msd = data;
2183 struct btd_device *dev = user_data;
2185 if (!bt_ad_add_manufacturer_data(dev->ad, msd->company, msd->data,
2189 g_dbus_emit_property_changed(dbus_conn, dev->path,
2190 DEVICE_INTERFACE, "ManufacturerData");
2193 void device_set_manufacturer_data(struct btd_device *dev, GSList *list,
2197 bt_ad_clear_manufacturer_data(dev->ad);
2199 g_slist_foreach(list, add_manufacturer_data, dev);
2202 static void add_service_data(void *data, void *user_data)
2204 struct eir_sd *sd = data;
2205 struct btd_device *dev = user_data;
2208 if (bt_string_to_uuid(&uuid, sd->uuid) < 0)
2211 if (!bt_ad_add_service_data(dev->ad, &uuid, sd->data, sd->data_len))
2214 g_dbus_emit_property_changed(dbus_conn, dev->path,
2215 DEVICE_INTERFACE, "ServiceData");
2218 void device_set_service_data(struct btd_device *dev, GSList *list,
2222 bt_ad_clear_service_data(dev->ad);
2224 g_slist_foreach(list, add_service_data, dev);
2227 static void add_data(void *data, void *user_data)
2229 struct eir_ad *ad = data;
2230 struct btd_device *dev = user_data;
2232 if (!bt_ad_add_data(dev->ad, ad->type, ad->data, ad->len))
2235 if (ad->type == EIR_TRANSPORT_DISCOVERY)
2236 g_dbus_emit_property_changed(dbus_conn, dev->path,
2241 void device_set_data(struct btd_device *dev, GSList *list,
2245 bt_ad_clear_data(dev->ad);
2247 g_slist_foreach(list, add_data, dev);
2250 static struct btd_service *find_connectable_service(struct btd_device *dev,
2254 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2255 struct btd_service *s = NULL;
2257 for (l = dev->services; l != NULL; l = g_slist_next(l)) {
2258 struct btd_service *service = l->data;
2259 struct btd_profile *p = btd_service_get_profile(service);
2261 if (!p->connect || !p->remote_uuid)
2264 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
2265 if (strcasecmp(uuid, p->remote_uuid) == 0)
2268 if (strcasecmp(uuid, p->remote_uuid) == 0) {
2270 if (ext_profile_is_registered_as_client_role(p) == TRUE) {
2278 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2286 static int service_prio_cmp(gconstpointer a, gconstpointer b)
2288 struct btd_profile *p1 = btd_service_get_profile(a);
2289 struct btd_profile *p2 = btd_service_get_profile(b);
2291 return p2->priority - p1->priority;
2294 static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
2296 struct btd_service *service;
2297 struct btd_profile *p;
2299 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2300 bool hs_hf_verify = FALSE;
2304 service = find_connectable_service(dev, uuid);
2306 return g_slist_prepend(dev->pending, service);
2307 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2308 else if ((service == NULL) &&
2309 (g_strcmp0(uuid, HFP_HS_UUID) == 0)) {
2310 DBG("HFP service not found check for HSP service");
2311 service = find_connectable_service(dev, HSP_HS_UUID);
2313 return g_slist_prepend(dev->pending, service);
2314 } else if (g_strcmp0(uuid, HID_UUID) == 0) {
2315 DBG("HID service not found, add HID service");
2316 btd_device_add_uuid(dev, uuid);
2317 service = find_connectable_service(dev, HID_UUID);
2319 return g_slist_prepend(dev->pending, service);
2322 return dev->pending;
2325 for (l = dev->services; l != NULL; l = g_slist_next(l)) {
2327 p = btd_service_get_profile(service);
2329 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2330 DBG("profile uuid %s", p->remote_uuid);
2331 if (g_strcmp0(p->remote_uuid, HSP_HS_UUID) == 0) {
2332 DBG("HSP service is found check for HFP service");
2333 struct btd_service *service;
2334 struct btd_profile *p;
2337 for (h = dev->services; h != NULL; h = g_slist_next(h)) {
2339 p = btd_service_get_profile(service);
2341 if (g_strcmp0(p->remote_uuid, HFP_HS_UUID) == 0) {
2342 DBG("HFP found,ignore HSP ");
2343 hs_hf_verify = TRUE;
2351 if (!p->auto_connect)
2354 if (g_slist_find(dev->pending, service))
2357 if (btd_service_get_state(service) !=
2358 BTD_SERVICE_STATE_DISCONNECTED)
2361 dev->pending = g_slist_insert_sorted(dev->pending, service,
2365 return dev->pending;
2368 int btd_device_connect_services(struct btd_device *dev, GSList *services)
2372 if (dev->pending || dev->connect || dev->browse)
2375 if (!btd_adapter_get_powered(dev->adapter))
2378 if (!dev->bredr_state.svc_resolved)
2382 for (l = services; l; l = g_slist_next(l)) {
2383 struct btd_service *service = l->data;
2385 dev->pending = g_slist_append(dev->pending, service);
2388 dev->pending = create_pending_list(dev, NULL);
2391 return connect_next(dev);
2394 static DBusMessage *connect_profiles(struct btd_device *dev, uint8_t bdaddr_type,
2395 DBusMessage *msg, const char *uuid)
2397 struct bearer_state *state = get_state(dev, bdaddr_type);
2400 DBG("%s %s, client %s", dev->path, uuid ? uuid : "(all)",
2401 dbus_message_get_sender(msg));
2403 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2404 if (dev->pending || dev->connect)
2405 return btd_error_in_progress(msg);
2407 if (dev->pending || dev->connect || dev->browse)
2408 return btd_error_in_progress(msg);
2411 if (!btd_adapter_get_powered(dev->adapter))
2412 return btd_error_not_ready(msg);
2414 btd_device_set_temporary(dev, false);
2416 if (!state->svc_resolved)
2417 goto resolve_services;
2419 dev->pending = create_pending_list(dev, uuid);
2420 if (!dev->pending) {
2421 if (dev->svc_refreshed) {
2422 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2423 if (!uuid && find_service_with_state(dev->services,
2424 BTD_SERVICE_STATE_CONNECTED))
2426 if (find_service_with_state(dev->services,
2427 BTD_SERVICE_STATE_CONNECTED))
2429 return dbus_message_new_method_return(msg);
2431 return btd_error_not_available(msg);
2434 goto resolve_services;
2437 err = connect_next(dev);
2439 if (err == -EALREADY)
2440 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2441 return btd_error_already_connected(msg);
2443 return dbus_message_new_method_return(msg);
2445 return btd_error_failed(msg, strerror(-err));
2448 dev->connect = dbus_message_ref(msg);
2453 DBG("Resolving services for %s", dev->path);
2455 if (bdaddr_type == BDADDR_BREDR)
2456 err = device_browse_sdp(dev, msg);
2458 err = device_browse_gatt(dev, msg);
2460 return btd_error_failed(msg, strerror(-err));
2465 #define NVAL_TIME ((time_t) -1)
2466 #define SEEN_TRESHHOLD 300
2468 static uint8_t select_conn_bearer(struct btd_device *dev)
2470 time_t bredr_last = NVAL_TIME, le_last = NVAL_TIME;
2471 time_t current = time(NULL);
2473 /* Prefer bonded bearer in case only one is bonded */
2474 if (dev->bredr_state.bonded && !dev->le_state.bonded )
2475 return BDADDR_BREDR;
2476 else if (!dev->bredr_state.bonded && dev->le_state.bonded)
2477 return dev->bdaddr_type;
2479 /* If the address is random it can only be connected over LE */
2480 if (dev->bdaddr_type == BDADDR_LE_RANDOM)
2481 return dev->bdaddr_type;
2483 if (dev->bredr_seen) {
2484 bredr_last = current - dev->bredr_seen;
2485 if (bredr_last > SEEN_TRESHHOLD)
2486 bredr_last = NVAL_TIME;
2490 le_last = current - dev->le_seen;
2491 if (le_last > SEEN_TRESHHOLD)
2492 le_last = NVAL_TIME;
2495 if (le_last == NVAL_TIME && bredr_last == NVAL_TIME)
2496 return dev->bdaddr_type;
2498 if (dev->bredr && (!dev->le || le_last == NVAL_TIME))
2499 return BDADDR_BREDR;
2501 if (dev->le && (!dev->bredr || bredr_last == NVAL_TIME))
2502 return dev->bdaddr_type;
2505 * Prefer BR/EDR if time is the same since it might be from an
2506 * advertisement with BR/EDR flag set.
2508 if (bredr_last <= le_last && btd_adapter_get_bredr(dev->adapter))
2509 return BDADDR_BREDR;
2511 return dev->bdaddr_type;
2514 static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
2517 struct btd_device *dev = user_data;
2518 uint8_t bdaddr_type;
2520 if (dev->bredr_state.connected) {
2522 * Check if services have been resolved and there is at list
2523 * one connected before switching to connect LE.
2525 if (dev->bredr_state.svc_resolved &&
2526 find_service_with_state(dev->services,
2527 BTD_SERVICE_STATE_CONNECTED))
2528 bdaddr_type = dev->bdaddr_type;
2530 bdaddr_type = BDADDR_BREDR;
2531 } else if (dev->le_state.connected && dev->bredr)
2532 bdaddr_type = BDADDR_BREDR;
2534 bdaddr_type = select_conn_bearer(dev);
2536 if (bdaddr_type != BDADDR_BREDR) {
2539 if (dev->le_state.connected)
2540 return dbus_message_new_method_return(msg);
2542 btd_device_set_temporary(dev, false);
2544 if (dev->disable_auto_connect) {
2545 dev->disable_auto_connect = FALSE;
2546 device_set_auto_connect(dev, TRUE);
2549 err = device_connect_le(dev);
2551 return btd_error_failed(msg, strerror(-err));
2553 dev->connect = dbus_message_ref(msg);
2558 return connect_profiles(dev, bdaddr_type, msg, NULL);
2561 static DBusMessage *connect_profile(DBusConnection *conn, DBusMessage *msg,
2564 struct btd_device *dev = user_data;
2565 const char *pattern;
2569 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
2571 return btd_error_invalid_args(msg);
2573 uuid = bt_name2string(pattern);
2574 reply = connect_profiles(dev, BDADDR_BREDR, msg, uuid);
2580 static void device_profile_disconnected(struct btd_device *dev,
2581 struct btd_profile *profile, int err)
2583 if (!dev->disconnect)
2587 g_dbus_send_message(dbus_conn,
2588 btd_error_failed(dev->disconnect,
2591 g_dbus_send_reply(dbus_conn, dev->disconnect,
2594 dbus_message_unref(dev->disconnect);
2595 dev->disconnect = NULL;
2598 static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
2601 struct btd_device *dev = user_data;
2602 struct btd_service *service;
2603 const char *pattern;
2607 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
2609 return btd_error_invalid_args(msg);
2611 uuid = bt_name2string(pattern);
2613 return btd_error_invalid_args(msg);
2615 service = find_connectable_service(dev, uuid);
2616 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2617 if ((service == NULL) && (g_strcmp0(uuid, HFP_HS_UUID) == 0)) {
2618 DBG("HFP service is not found check for HSP service");
2619 service = find_connectable_service(dev, HSP_HS_UUID);
2625 return btd_error_invalid_args(msg);
2627 if (dev->disconnect)
2628 return btd_error_in_progress(msg);
2630 dev->disconnect = dbus_message_ref(msg);
2632 err = btd_service_disconnect(service);
2636 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2637 if (dev->disconnect)
2639 dbus_message_unref(dev->disconnect);
2640 dev->disconnect = NULL;
2642 if (err == -ENOTSUP)
2643 return btd_error_not_supported(msg);
2645 return btd_error_failed(msg, strerror(-err));
2648 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2649 static DBusMessage *disconnect_ext_profile(DBusConnection *conn,
2650 DBusMessage *msg, void *user_data)
2652 struct btd_device *dev = user_data;
2653 struct btd_profile *profile;
2654 struct btd_service *service;
2655 const char *sender, *path;
2659 sender = dbus_message_get_sender(msg);
2661 DBG("sender %s", sender);
2663 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
2665 return btd_error_invalid_args(msg);
2667 profile = btd_profile_find_ext(sender, path);
2669 return btd_error_invalid_args(msg);
2671 l = find_service_with_profile(dev->services, profile);
2673 return btd_error_invalid_args(msg);
2677 if (dev->disconnect)
2678 return btd_error_in_progress(msg);
2680 dev->disconnect = dbus_message_ref(msg);
2682 err = btd_service_disconnect(service);
2686 if (dev->disconnect)
2687 dbus_message_unref(dev->disconnect);
2688 dev->disconnect = NULL;
2690 if (err == -ENOTSUP)
2691 return btd_error_not_supported(msg);
2693 return btd_error_failed(msg, strerror(-err));
2697 static void store_services(struct btd_device *device)
2699 char filename[PATH_MAX];
2708 if (device_address_is_private(device)) {
2709 DBG("Can't store services for private addressed device %s",
2714 sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
2715 prim_uuid = bt_uuid2string(&uuid);
2716 if (prim_uuid == NULL)
2719 ba2str(&device->bdaddr, dst_addr);
2721 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2723 ba2str(device->rpa, dst_addr);
2726 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes",
2727 btd_adapter_get_storage_dir(device->adapter),
2729 key_file = g_key_file_new();
2731 for (l = device->primaries; l; l = l->next) {
2732 struct gatt_primary *primary = l->data;
2733 char handle[6], uuid_str[33];
2736 sprintf(handle, "%hu", primary->range.start);
2738 bt_string2uuid(&uuid, primary->uuid);
2739 sdp_uuid128_to_uuid(&uuid);
2741 switch (uuid.type) {
2743 sprintf(uuid_str, "%4.4X", uuid.value.uuid16);
2746 sprintf(uuid_str, "%8.8X", uuid.value.uuid32);
2749 for (i = 0; i < 16; i++)
2750 sprintf(uuid_str + (i * 2), "%2.2X",
2751 uuid.value.uuid128.data[i]);
2757 g_key_file_set_string(key_file, handle, "UUID", prim_uuid);
2758 g_key_file_set_string(key_file, handle, "Value", uuid_str);
2759 g_key_file_set_integer(key_file, handle, "EndGroupHandle",
2760 primary->range.end);
2763 data = g_key_file_to_data(key_file, &length, NULL);
2765 create_file(filename, S_IRUSR | S_IWUSR);
2766 g_file_set_contents(filename, data, length, NULL);
2771 g_key_file_free(key_file);
2775 struct btd_device *device;
2780 static void db_hash_read_value_cb(struct gatt_db_attribute *attrib,
2781 int err, const uint8_t *value,
2782 size_t length, void *user_data)
2784 const uint8_t **hash = user_data;
2786 if (err || (length != 16))
2792 static void store_desc(struct gatt_db_attribute *attr, void *user_data)
2794 struct gatt_saver *saver = user_data;
2795 GKeyFile *key_file = saver->key_file;
2796 char handle[6], value[100], uuid_str[MAX_LEN_UUID_STR];
2797 const bt_uuid_t *uuid;
2799 uint16_t handle_num;
2801 handle_num = gatt_db_attribute_get_handle(attr);
2802 sprintf(handle, "%04hx", handle_num);
2804 uuid = gatt_db_attribute_get_type(attr);
2805 bt_uuid_to_string(uuid, uuid_str, sizeof(uuid_str));
2807 bt_uuid16_create(&ext_uuid, GATT_CHARAC_EXT_PROPER_UUID);
2808 if (!bt_uuid_cmp(uuid, &ext_uuid) && saver->ext_props)
2809 sprintf(value, "%04hx:%s", saver->ext_props, uuid_str);
2811 sprintf(value, "%s", uuid_str);
2813 g_key_file_set_string(key_file, "Attributes", handle, value);
2816 static void store_chrc(struct gatt_db_attribute *attr, void *user_data)
2818 struct gatt_saver *saver = user_data;
2819 GKeyFile *key_file = saver->key_file;
2820 char handle[6], value[100], uuid_str[MAX_LEN_UUID_STR];
2821 uint16_t handle_num, value_handle;
2823 bt_uuid_t uuid, hash_uuid;
2825 if (!gatt_db_attribute_get_char_data(attr, &handle_num, &value_handle,
2826 &properties, &saver->ext_props,
2828 warn("Error storing characteristic - can't get data");
2832 sprintf(handle, "%04hx", handle_num);
2833 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
2835 /* Store Database Hash value if available */
2836 bt_uuid16_create(&hash_uuid, GATT_CHARAC_DB_HASH);
2837 if (!bt_uuid_cmp(&uuid, &hash_uuid)) {
2838 const uint8_t *hash = NULL;
2840 attr = gatt_db_get_attribute(saver->device->db, value_handle);
2842 gatt_db_attribute_read(attr, 0, BT_ATT_OP_READ_REQ, NULL,
2843 db_hash_read_value_cb, &hash);
2845 sprintf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hhx:"
2846 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
2847 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
2848 "%02hhx%02hhx:%s", value_handle, properties,
2849 hash[0], hash[1], hash[2], hash[3],
2850 hash[4], hash[5], hash[6], hash[7],
2851 hash[8], hash[9], hash[10], hash[11],
2852 hash[12], hash[13], hash[14], hash[15],
2855 sprintf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hhx:%s",
2856 value_handle, properties, uuid_str);
2859 sprintf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hhx:%s",
2860 value_handle, properties, uuid_str);
2862 g_key_file_set_string(key_file, "Attributes", handle, value);
2864 gatt_db_service_foreach_desc(attr, store_desc, saver);
2867 static void store_incl(struct gatt_db_attribute *attr, void *user_data)
2869 struct gatt_saver *saver = user_data;
2870 GKeyFile *key_file = saver->key_file;
2871 struct gatt_db_attribute *service;
2872 char handle[6], value[100], uuid_str[MAX_LEN_UUID_STR];
2873 uint16_t handle_num, start, end;
2876 if (!gatt_db_attribute_get_incl_data(attr, &handle_num, &start, &end)) {
2877 warn("Error storing included service - can't get data");
2881 service = gatt_db_get_attribute(saver->device->db, start);
2883 warn("Error storing included service - can't find it");
2887 sprintf(handle, "%04hx", handle_num);
2889 gatt_db_attribute_get_service_uuid(service, &uuid);
2890 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
2891 sprintf(value, GATT_INCLUDE_UUID_STR ":%04hx:%04hx:%s", start,
2894 g_key_file_set_string(key_file, "Attributes", handle, value);
2897 static void store_service(struct gatt_db_attribute *attr, void *user_data)
2899 struct gatt_saver *saver = user_data;
2900 GKeyFile *key_file = saver->key_file;
2901 char uuid_str[MAX_LEN_UUID_STR], handle[6], value[256];
2902 uint16_t start, end;
2907 if (!gatt_db_attribute_get_service_data(attr, &start, &end, &primary,
2909 warn("Error storing service - can't get data");
2913 sprintf(handle, "%04hx", start);
2915 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
2918 type = GATT_PRIM_SVC_UUID_STR;
2920 type = GATT_SND_SVC_UUID_STR;
2922 sprintf(value, "%s:%04hx:%s", type, end, uuid_str);
2924 g_key_file_set_string(key_file, "Attributes", handle, value);
2926 gatt_db_service_foreach_incl(attr, store_incl, saver);
2927 gatt_db_service_foreach_char(attr, store_chrc, saver);
2930 static void store_gatt_db(struct btd_device *device)
2932 char filename[PATH_MAX];
2937 struct gatt_saver saver;
2939 if (device_address_is_private(device)) {
2940 DBG("Can't store GATT db for private addressed device %s",
2945 if (!gatt_cache_is_enabled(device))
2948 ba2str(&device->bdaddr, dst_addr);
2950 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
2951 btd_adapter_get_storage_dir(device->adapter),
2953 create_file(filename, S_IRUSR | S_IWUSR);
2955 key_file = g_key_file_new();
2956 g_key_file_load_from_file(key_file, filename, 0, NULL);
2958 /* Remove current attributes since it might have changed */
2959 g_key_file_remove_group(key_file, "Attributes", NULL);
2961 saver.key_file = key_file;
2962 saver.device = device;
2964 gatt_db_foreach_service(device->db, NULL, store_service, &saver);
2966 data = g_key_file_to_data(key_file, &length, NULL);
2967 g_file_set_contents(filename, data, length, NULL);
2970 g_key_file_free(key_file);
2974 static void browse_request_complete(struct browse_req *req, uint8_t type,
2975 uint8_t bdaddr_type, int err)
2977 struct btd_device *dev = req->device;
2978 DBusMessage *reply = NULL;
2981 if (req->type != type)
2987 if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE, "Pair")) {
2988 if (!device_is_paired(dev, bdaddr_type)) {
2989 reply = btd_error_failed(req->msg, "Not paired");
2993 if (dev->pending_paired) {
2994 g_dbus_emit_property_changed(dbus_conn, dev->path,
2995 DEVICE_INTERFACE, "Paired");
2996 dev->pending_paired = false;
2999 /* Disregard browse errors in case of Pair */
3000 reply = g_dbus_create_reply(req->msg, DBUS_TYPE_INVALID);
3005 /* Fallback to LE bearer if supported */
3006 if (err == -EHOSTDOWN && bdaddr_type == BDADDR_BREDR &&
3007 dev->le && !dev->le_state.connected) {
3008 err = device_connect_le(dev);
3012 reply = btd_error_failed(req->msg, strerror(-err));
3016 /* if successfully resolved services we need to free browsing request
3017 * before passing message back to connect functions, otherwise
3018 * device->browse is set and "InProgress" error is returned instead
3019 * of actually connecting services
3021 msg = dbus_message_ref(req->msg);
3022 browse_request_free(req);
3025 if (dbus_message_is_method_call(msg, DEVICE_INTERFACE, "Connect"))
3026 reply = dev_connect(dbus_conn, msg, dev);
3027 else if (dbus_message_is_method_call(msg, DEVICE_INTERFACE,
3029 reply = connect_profile(dbus_conn, msg, dev);
3031 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3033 dbus_message_unref(msg);
3037 g_dbus_send_message(dbus_conn, reply);
3040 browse_request_free(req);
3043 static void device_set_svc_refreshed(struct btd_device *device, bool value)
3045 if (device->svc_refreshed == value)
3048 device->svc_refreshed = value;
3050 g_dbus_emit_property_changed(dbus_conn, device->path,
3051 DEVICE_INTERFACE, "ServicesResolved");
3054 static void device_svc_resolved(struct btd_device *dev, uint8_t browse_type,
3055 uint8_t bdaddr_type, int err)
3057 struct bearer_state *state = get_state(dev, bdaddr_type);
3058 struct browse_req *req = dev->browse;
3060 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3061 DBG("%s bdaddr_type %d err %d", dev->path, bdaddr_type, err);
3063 DBG("%s err %d", dev->path, err);
3066 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3067 state->svc_resolved = true;
3070 state->svc_resolved = true;
3073 /* Disconnection notification can happen before this function
3074 * gets called, so don't set svc_refreshed for a disconnected
3077 if (state->connected)
3078 device_set_svc_refreshed(dev, true);
3080 g_slist_free_full(dev->eir_uuids, g_free);
3081 dev->eir_uuids = NULL;
3083 if (dev->pending_paired) {
3084 g_dbus_emit_property_changed(dbus_conn, dev->path,
3085 DEVICE_INTERFACE, "Paired");
3086 dev->pending_paired = false;
3089 if (!dev->temporary) {
3090 store_device_info(dev);
3092 if (bdaddr_type != BDADDR_BREDR && err == 0)
3093 store_services(dev);
3096 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3098 browse_request_complete(req, browse_type, bdaddr_type, err);
3101 while (dev->svc_callbacks) {
3102 struct svc_callback *cb = dev->svc_callbacks->data;
3104 if (cb->idle_id > 0)
3105 g_source_remove(cb->idle_id);
3107 cb->func(dev, err, cb->user_data);
3109 dev->svc_callbacks = g_slist_delete_link(dev->svc_callbacks,
3110 dev->svc_callbacks);
3114 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3118 /* If bdaddr_type is LE but req is for SDP, don't complete browse req. */
3119 if (bdaddr_type != BDADDR_BREDR && req->search_uuid) {
3120 DBG("Discover comp. is for LE but browse req. is for SDP.");
3124 browse_request_complete(req, browse_type, bdaddr_type, err);
3128 static struct bonding_req *bonding_request_new(DBusMessage *msg,
3129 struct btd_device *device,
3130 uint8_t bdaddr_type,
3131 struct agent *agent)
3133 struct bonding_req *bonding;
3136 ba2str(&device->bdaddr, addr);
3137 DBG("Requesting bonding for %s", addr);
3139 bonding = g_new0(struct bonding_req, 1);
3141 bonding->msg = dbus_message_ref(msg);
3142 bonding->bdaddr_type = bdaddr_type;
3144 bonding->cb_iter = btd_adapter_pin_cb_iter_new(device->adapter);
3146 /* Marks the bonding start time for the first attempt on request
3147 * construction. The following attempts will be updated on
3148 * device_bonding_retry. */
3149 clock_gettime(CLOCK_MONOTONIC, &bonding->attempt_start_time);
3152 bonding->agent = agent_ref(agent);
3157 void device_bonding_restart_timer(struct btd_device *device)
3159 if (!device || !device->bonding)
3162 clock_gettime(CLOCK_MONOTONIC, &device->bonding->attempt_start_time);
3165 static void bonding_request_stop_timer(struct bonding_req *bonding)
3167 struct timespec current;
3169 clock_gettime(CLOCK_MONOTONIC, ¤t);
3171 /* Compute the time difference in ms. */
3172 bonding->last_attempt_duration_ms =
3173 (current.tv_sec - bonding->attempt_start_time.tv_sec) * 1000L +
3174 (current.tv_nsec - bonding->attempt_start_time.tv_nsec)
3178 /* Returns the duration of the last bonding attempt in milliseconds. The
3179 * duration is measured starting from the latest of the following three
3180 * events and finishing when the Command complete event is received for the
3181 * authentication request:
3182 * - MGMT_OP_PAIR_DEVICE is sent,
3183 * - MGMT_OP_PIN_CODE_REPLY is sent and
3184 * - Command complete event is received for the sent MGMT_OP_PIN_CODE_REPLY.
3186 long device_bonding_last_duration(struct btd_device *device)
3188 struct bonding_req *bonding = device->bonding;
3193 return bonding->last_attempt_duration_ms;
3196 static void create_bond_req_exit(DBusConnection *conn, void *user_data)
3198 struct btd_device *device = user_data;
3201 ba2str(&device->bdaddr, addr);
3202 DBG("%s: requestor exited before bonding was completed", addr);
3205 device_cancel_authentication(device, FALSE);
3207 if (device->bonding) {
3208 device->bonding->listener_id = 0;
3209 device_request_disconnect(device, NULL);
3213 static void bonding_request_free(struct bonding_req *bonding)
3218 if (bonding->listener_id)
3219 g_dbus_remove_watch(dbus_conn, bonding->listener_id);
3222 dbus_message_unref(bonding->msg);
3224 if (bonding->cb_iter)
3225 g_free(bonding->cb_iter);
3227 if (bonding->agent) {
3228 agent_cancel(bonding->agent);
3229 agent_unref(bonding->agent);
3230 bonding->agent = NULL;
3233 if (bonding->retry_timer)
3234 g_source_remove(bonding->retry_timer);
3236 if (bonding->device)
3237 bonding->device->bonding = NULL;
3242 static DBusMessage *pair_device(DBusConnection *conn, DBusMessage *msg,
3245 struct btd_device *device = data;
3246 struct btd_adapter *adapter = device->adapter;
3247 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3248 struct bearer_state *state;
3250 uint8_t bdaddr_type;
3252 struct agent *agent;
3253 struct bonding_req *bonding;
3255 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3257 bool connect_le = FALSE;
3258 uint8_t link_type = DEV_CONNECTED_NONE;
3262 btd_device_set_temporary(device, false);
3264 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3265 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_BYTE, &conn_type,
3266 DBUS_TYPE_INVALID) == FALSE)
3268 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID))
3270 return btd_error_invalid_args(msg);
3272 if (device->bonding)
3273 return btd_error_in_progress(msg);
3275 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3276 if (conn_type == DEV_CONN_DEFAULT) {
3277 link_type = device_get_connected_state(device);
3279 if (link_type == DEV_CONNECTED_BREDR) {
3280 if (device_is_bonded(device, DEV_CONN_BREDR))
3281 return btd_error_already_exists(msg);
3282 conn_type = DEV_CONN_BREDR;
3283 } else if (link_type == DEV_CONNECTED_LE) {
3284 if (device_is_bonded(device, DEV_CONN_LE))
3285 return btd_error_already_exists(msg);
3286 conn_type = DEV_CONN_LE;
3288 if (device_is_bonded(device, DEV_CONN_BREDR))
3289 return btd_error_already_exists(msg);
3290 else if (device_is_bonded(device, DEV_CONN_LE))
3291 return btd_error_already_exists(msg);
3294 conn_type = DEV_CONN_BREDR;
3295 else if (device->le)
3296 conn_type = DEV_CONN_LE;
3298 conn_type = DEV_CONN_BREDR;
3301 if (device_is_bonded(device, conn_type))
3302 return btd_error_already_exists(msg);
3304 bdaddr_type = device->bdaddr_type;
3306 if (device->bredr_state.bonded)
3307 bdaddr_type = device->bdaddr_type;
3308 else if (device->le_state.bonded)
3309 bdaddr_type = BDADDR_BREDR;
3311 bdaddr_type = select_conn_bearer(device);
3313 state = get_state(device, bdaddr_type);
3316 return btd_error_already_exists(msg);
3319 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3320 DBG("conn_type %d, link_type %d, bdaddr_type %d, device->bredr %d",
3321 conn_type, link_type, bdaddr_type, device->bredr);
3322 if (conn_type == DEV_CONN_LE &&
3323 (device_is_bredrle(device) || bdaddr_type != BDADDR_BREDR)) {
3324 DBG("LE Connect request");
3329 sender = dbus_message_get_sender(msg);
3331 agent = agent_get(sender);
3333 io_cap = agent_get_io_capability(agent);
3335 io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
3337 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3338 if ((conn_type == DEV_CONN_LE && bdaddr_type != BDADDR_BREDR) ||
3340 bonding = bonding_request_new(msg, device, bdaddr_type, agent);
3342 bonding = bonding_request_new(msg, device, BDADDR_BREDR, agent);
3344 bonding = bonding_request_new(msg, device, bdaddr_type, agent);
3350 bonding->listener_id = g_dbus_add_disconnect_watch(dbus_conn,
3351 sender, create_bond_req_exit,
3354 device->bonding = bonding;
3355 bonding->device = device;
3357 /* Due to a bug in the kernel we might loose out on ATT commands
3358 * that arrive during the SMP procedure, so connect the ATT
3359 * channel first and only then start pairing (there's code for
3360 * this in the ATT connect callback)
3362 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3363 if (((conn_type == DEV_CONN_LE && bdaddr_type != BDADDR_BREDR) ||
3364 (connect_le)) && !device->le_state.connected)
3365 err = device_connect_le(device);
3366 else if (connect_le) /* Send bonding request if LE is already connected*/
3367 err = adapter_create_bonding(adapter, &device->bdaddr,
3368 bdaddr_type, io_cap);
3370 err = adapter_create_bonding(adapter, &device->bdaddr,
3371 BDADDR_BREDR, io_cap);
3373 if (bdaddr_type != BDADDR_BREDR) {
3374 if (!state->connected && btd_le_connect_before_pairing())
3375 err = device_connect_le(device);
3377 err = adapter_create_bonding(adapter, &device->bdaddr,
3378 device->bdaddr_type,
3381 err = adapter_create_bonding(adapter, &device->bdaddr,
3382 BDADDR_BREDR, io_cap);
3387 bonding_request_free(device->bonding);
3388 return btd_error_failed(msg, strerror(-err));
3394 static DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
3397 case MGMT_STATUS_SUCCESS:
3398 return dbus_message_new_method_return(msg);
3400 case MGMT_STATUS_CONNECT_FAILED:
3401 return dbus_message_new_error(msg,
3402 ERROR_INTERFACE ".ConnectionAttemptFailed",
3404 case MGMT_STATUS_TIMEOUT:
3405 return dbus_message_new_error(msg,
3406 ERROR_INTERFACE ".AuthenticationTimeout",
3407 "Authentication Timeout");
3408 case MGMT_STATUS_BUSY:
3409 case MGMT_STATUS_REJECTED:
3410 return dbus_message_new_error(msg,
3411 ERROR_INTERFACE ".AuthenticationRejected",
3412 "Authentication Rejected");
3413 case MGMT_STATUS_CANCELLED:
3414 case MGMT_STATUS_NO_RESOURCES:
3415 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3416 case MGMT_STATUS_DISCONNECTED:
3418 return dbus_message_new_error(msg,
3419 ERROR_INTERFACE ".AuthenticationCanceled",
3420 "Authentication Canceled");
3421 case MGMT_STATUS_ALREADY_PAIRED:
3422 return dbus_message_new_error(msg,
3423 ERROR_INTERFACE ".AlreadyExists",
3426 return dbus_message_new_error(msg,
3427 ERROR_INTERFACE ".AuthenticationFailed",
3428 "Authentication Failed");
3432 static void device_cancel_bonding(struct btd_device *device, uint8_t status)
3434 struct bonding_req *bonding = device->bonding;
3441 ba2str(&device->bdaddr, addr);
3442 DBG("Canceling bonding request for %s", addr);
3445 device_cancel_authentication(device, FALSE);
3447 reply = new_authentication_return(bonding->msg, status);
3448 g_dbus_send_message(dbus_conn, reply);
3450 bonding_request_cancel(bonding);
3451 bonding_request_free(bonding);
3454 static DBusMessage *cancel_pairing(DBusConnection *conn, DBusMessage *msg,
3457 struct btd_device *device = data;
3458 struct bonding_req *req = device->bonding;
3463 return btd_error_does_not_exist(msg);
3465 device_cancel_bonding(device, MGMT_STATUS_CANCELLED);
3467 return dbus_message_new_method_return(msg);
3470 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3471 static DBusMessage *discover_services(DBusConnection *conn,
3472 DBusMessage *msg, void *user_data)
3474 struct btd_device *device = user_data;
3475 const char *pattern;
3479 return btd_error_in_progress(msg);
3481 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
3482 DBUS_TYPE_INVALID) == FALSE)
3483 return btd_error_invalid_args(msg);
3485 err = device_browse_sdp(device, msg);
3492 return btd_error_failed(msg,
3493 "Unable to search the SDP services");
3496 static const char *browse_request_get_requestor(struct browse_req *req)
3501 return dbus_message_get_sender(req->msg);
3504 static void iter_append_record(DBusMessageIter *dict, uint32_t handle,
3507 DBusMessageIter entry;
3509 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
3512 dbus_message_iter_append_basic(&entry, DBUS_TYPE_UINT32, &handle);
3514 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &record);
3516 dbus_message_iter_close_container(dict, &entry);
3519 static void discover_services_reply(struct browse_req *req, int err,
3523 DBusMessageIter iter, dict;
3532 if (err == -EHOSTDOWN)
3533 err_if = ERROR_INTERFACE ".ConnectionAttemptFailed";
3535 err_if = ERROR_INTERFACE ".Failed";
3537 reply = dbus_message_new_error(req->msg, err_if,
3539 g_dbus_send_message(dbus_conn, reply);
3543 reply = dbus_message_new_method_return(req->msg);
3547 dbus_message_iter_init_append(reply, &iter);
3549 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
3550 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
3551 DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_STRING_AS_STRING
3552 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
3554 for (seq = recs; seq; seq = seq->next) {
3555 sdp_record_t *rec = (sdp_record_t *) seq->data;
3561 result = g_string_new(NULL);
3563 convert_sdp_record_to_xml(rec, result,
3564 (void *) g_string_append);
3567 if (!g_utf8_validate(result->str, -1, NULL)) {
3570 DBG("UTF8 invalid string, make valid");
3571 ptr = g_utf8_make_valid(result->str, -1);
3572 iter_append_record(&dict, rec->handle, ptr);
3575 iter_append_record(&dict, rec->handle, result->str);
3579 g_string_free(result, TRUE);
3582 dbus_message_iter_close_container(&iter, &dict);
3584 g_dbus_send_message(dbus_conn, reply);
3587 static DBusMessage *cancel_discover(DBusConnection *conn,
3588 DBusMessage *msg, void *user_data)
3590 struct btd_device *device = user_data;
3591 const char *sender = dbus_message_get_sender(msg);
3592 const char *requestor;
3594 if (!device->browse)
3595 return btd_error_does_not_exist(msg);
3597 if (!dbus_message_is_method_call(device->browse->msg, DEVICE_INTERFACE,
3598 "DiscoverServices"))
3599 return btd_error_not_authorized(msg);
3601 requestor = browse_request_get_requestor(device->browse);
3603 /* only the discover requestor can cancel the inquiry process */
3604 if (!requestor || !g_str_equal(requestor, sender))
3605 return btd_error_not_authorized(msg);
3607 discover_services_reply(device->browse, -ECANCELED, NULL);
3610 browse_request_cancel(device->browse);
3612 return dbus_message_new_method_return(msg);
3615 void device_set_gatt_connected(struct btd_device *device, gboolean connected)
3617 if (device == NULL) {
3618 error("device is NULL");
3622 if (device->gatt_connected == connected) {
3623 error("same state change for gatt_connected : %d", connected);
3626 DBG("GattConnected %d", connected);
3628 device->gatt_connected = connected;
3629 g_dbus_emit_property_changed(dbus_conn, device->path,
3630 DEVICE_INTERFACE, "GattConnected");
3633 static DBusMessage *connect_le(DBusConnection *conn, DBusMessage *msg,
3636 struct btd_device *dev = user_data;
3637 dbus_bool_t auto_connect = FALSE;
3642 * If a LE connection is requested without device discovery,
3643 * we try to get device object. Here, technology can be updated
3644 * if there is matched device object. Or, a new device object
3647 dev = btd_adapter_get_device(dev->adapter, &dev->bdaddr,
3650 error("Unable to get device object");
3651 return btd_error_not_supported(msg);
3655 if (dev->le_state.connected)
3656 return dbus_message_new_method_return(msg);
3658 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &auto_connect,
3660 return btd_error_invalid_args(msg);
3662 btd_device_set_temporary(dev, false);
3665 DBG("Start BLE auto connection");
3666 dev->disable_auto_connect = FALSE;
3667 device_set_auto_connect(dev, TRUE);
3669 return dbus_message_new_method_return(msg);
3672 err = device_connect_le(dev);
3674 return btd_error_failed(msg, strerror(-err));
3676 dev->connect = dbus_message_ref(msg);
3681 static DBusMessage *disconnect_le(DBusConnection *conn, DBusMessage *msg,
3684 struct btd_device *dev = user_data;
3687 return btd_error_not_supported(msg);
3690 * Disable connections through passive sccanning
3692 if (dev->auto_connect) {
3693 DBG("Stop BLE auto connection");
3694 dev->disable_auto_connect = FALSE;
3695 device_set_auto_connect(dev, FALSE);
3697 if (!dev->le_state.connected) {
3698 g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
3703 device_request_disconnect(dev, msg);
3708 static DBusMessage *connect_ipsp(DBusConnection *conn, DBusMessage *msg,
3711 struct btd_device *device = user_data;
3713 DBG("bdaddr_type %d", device->bdaddr_type);
3715 if (device->bdaddr_type == BDADDR_BREDR) {
3717 device->bdaddr_type = BDADDR_LE_PUBLIC;
3719 device = btd_adapter_get_device(device->adapter,
3720 &device->bdaddr, BDADDR_LE_PUBLIC);
3722 return btd_error_no_such_adapter(msg);
3726 if (device->ipsp_connected)
3727 return btd_error_already_connected(msg);
3729 /* Initiate Connection for 6Lowan*/
3730 if (btd_adapter_connect_ipsp(device->adapter, &device->bdaddr,
3731 device->bdaddr_type) != 0)
3732 return btd_error_failed(msg, "ConnectFailed");
3734 return dbus_message_new_method_return(msg);;
3737 static DBusMessage *disconnect_ipsp(DBusConnection *conn, DBusMessage *msg,
3740 struct btd_device *device = user_data;
3741 DBG("bdaddr_type %d", device->bdaddr_type);
3743 if (device->bdaddr_type == BDADDR_BREDR)
3744 return btd_error_not_supported(msg);
3746 if (!device->ipsp_connected)
3747 return btd_error_not_connected(msg);
3749 /* Disconnect the 6Lowpan connection */
3750 if (btd_adapter_disconnect_ipsp(device->adapter, &device->bdaddr,
3751 device->bdaddr_type) != 0)
3752 return btd_error_failed(msg, "DisconnectFailed");
3754 /* TODO: Handle disconnection of GATT connection, If the connection
3755 * is established as part of IPSP connection. */
3757 return dbus_message_new_method_return(msg);;
3760 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3761 static GSList *find_otc_conn_info(GSList *list, const char *path)
3765 for (l = list; l != NULL; l = g_slist_next(l)) {
3766 struct otc_conn_info *info = l->data;
3768 if (g_strcmp0(info->dev_path, path) == 0)
3775 static gboolean otc_disconnected_cb(GIOChannel *chan, GIOCondition cond,
3778 struct otc_conn_info *conn_info;
3779 const char *dev_path = (const char *) user_data;
3782 DBG("OTC Disconnected");
3784 l = find_otc_conn_info(otc_connection_list, dev_path);
3788 conn_info = l->data;
3789 conn_info->otc_connected = false;
3791 g_dbus_emit_signal(dbus_conn, dev_path,
3792 DEVICE_INTERFACE, "OtcDisconnected",
3795 if (conn_info->io) {
3796 g_io_channel_shutdown(conn_info->io, TRUE, NULL);
3797 g_io_channel_unref(conn_info->io);
3800 otc_connection_list = g_slist_remove(otc_connection_list, conn_info);
3806 static void otc_connect_cb(GIOChannel *chan, GError *gerr,
3809 const char *dev_path;
3811 struct otc_conn_info *conn_info = NULL;
3812 DBusMessage *msg = NULL;
3813 DBusMessageIter iter;
3819 dev_path = (const char *) user_data;
3820 l = find_otc_conn_info(otc_connection_list, dev_path);
3825 conn_info = l->data;
3826 conn_info->otc_connected = true;
3828 fd = g_io_channel_unix_get_fd(chan);
3830 DBG("OTC Connected fd [%d], role [%s]",
3831 fd, conn_info->role ? "server" : "client");
3832 DBG("dev_path [%s]", dev_path);
3834 g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
3835 otc_disconnected_cb, (gpointer) dev_path);
3837 if (conn_info->role == BT_OTP_CLIENT_ROLE) {
3838 msg = dbus_message_new_method_call(BT_OTC_SERVICE_NAME,
3840 BT_OTC_INTERFACE_NAME,
3842 } else if (conn_info->role == BT_OTP_SERVER_ROLE) {
3843 msg = dbus_message_new_method_call(BT_OTS_SERVICE_NAME,
3845 BT_OTS_INTERFACE_NAME,
3850 error("Unable to create NewConnection call");
3854 dbus_message_iter_init_append(msg, &iter);
3856 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &dev_path);
3858 dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd);
3860 if (!g_dbus_send_message(dbus_conn, msg)) {
3861 error("sending NewConnection failed");
3862 dbus_message_unref(msg);
3866 int btd_adapter_connect_otc(struct btd_device *device)
3868 struct btd_adapter *adapter = device_get_adapter(device);
3869 const bdaddr_t *src = btd_adapter_get_address(adapter);
3870 uint8_t src_type = btd_adapter_get_le_address_type(adapter);
3871 const bdaddr_t *dest = device_get_address(device);
3872 uint8_t dest_type = device->bdaddr_type;
3873 struct otc_conn_info *conn_info = NULL;
3874 const char *dev_path = device_get_path(device);
3875 GError *gerr = NULL;
3877 conn_info = g_malloc0(sizeof(struct otc_conn_info));
3879 conn_info->io = bt_io_connect(otc_connect_cb,
3880 (gpointer) dev_path, NULL, &gerr,
3881 BT_IO_OPT_SOURCE_BDADDR, src,
3882 BT_IO_OPT_SOURCE_TYPE, src_type,
3883 BT_IO_OPT_DEST_BDADDR, dest,
3884 BT_IO_OPT_DEST_TYPE, dest_type,
3885 BT_IO_OPT_PSM, OTP_PSM,
3886 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
3889 if (!conn_info->io) {
3890 error("OTC Connect failed : %s", gerr->message);
3896 conn_info->dev_path = dev_path;
3897 conn_info->role = BT_OTP_CLIENT_ROLE;
3898 conn_info->otc_connected = false;
3899 g_io_channel_set_close_on_unref(conn_info->io, FALSE);
3901 otc_connection_list = g_slist_append(otc_connection_list, conn_info);
3905 static DBusMessage *connect_otc(DBusConnection *conn, DBusMessage *msg,
3908 struct btd_device *device = user_data;
3912 return btd_error_invalid_args(msg);
3914 l = find_otc_conn_info(otc_connection_list, device_get_path(device));
3917 struct otc_conn_info *info = l->data;
3918 if (info->otc_connected)
3919 return btd_error_already_connected(msg);
3921 return btd_error_busy(msg);
3924 if (btd_adapter_connect_otc(device) != 0)
3925 return btd_error_failed(msg, "ConnectFailed");
3927 return dbus_message_new_method_return(msg);
3930 static DBusMessage *disconnect_otc(DBusConnection *conn, DBusMessage *msg,
3933 struct btd_device *device = user_data;
3934 struct otc_conn_info *info = NULL;
3938 l = find_otc_conn_info(otc_connection_list, device_get_path(device));
3941 return btd_error_does_not_exist(msg);
3945 if (!info->otc_connected)
3946 return btd_error_not_connected(msg);
3948 sock = g_io_channel_unix_get_fd(info->io);
3950 shutdown(sock, SHUT_RDWR);
3952 g_io_channel_shutdown(info->io, FALSE, NULL);
3954 g_io_channel_unref(info->io);
3957 return dbus_message_new_method_return(msg);
3960 int btd_adapter_listen_otc(struct btd_device *device)
3962 struct btd_adapter *adapter = device_get_adapter(device);
3963 const bdaddr_t *src = btd_adapter_get_address(adapter);
3964 uint8_t type = btd_adapter_get_le_address_type(adapter);
3965 struct otc_conn_info *conn_info = NULL;
3966 const char *dev_path = device_get_path(device);
3967 GError *gerr = NULL;
3969 conn_info = g_malloc0(sizeof(struct otc_conn_info));
3971 conn_info->io = bt_io_listen(otc_connect_cb, NULL, (gpointer) dev_path,
3973 BT_IO_OPT_SOURCE_BDADDR, src,
3974 BT_IO_OPT_SOURCE_TYPE, type,
3975 BT_IO_OPT_PSM, OTP_PSM,
3976 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
3979 if (!conn_info->io) {
3980 error("OTC Listen failed : %s", gerr->message);
3986 conn_info->dev_path = dev_path;
3987 conn_info->otc_connected = false;
3988 conn_info->role = BT_OTP_SERVER_ROLE;
3989 g_io_channel_set_close_on_unref(conn_info->io, FALSE);
3991 otc_connection_list = g_slist_append(otc_connection_list, conn_info);
3995 static DBusMessage *listen_otc(DBusConnection *conn, DBusMessage *msg,
3998 struct btd_device *device = user_data;
4002 return btd_error_invalid_args(msg);
4004 l = find_otc_conn_info(otc_connection_list, device_get_path(device));
4007 struct otc_conn_info *info = l->data;
4008 if (info->otc_connected)
4009 return btd_error_already_connected(msg);
4011 return btd_error_busy(msg);
4014 if (btd_adapter_listen_otc(device) != 0)
4015 return btd_error_failed(msg, "ListenFailed");
4017 return dbus_message_new_method_return(msg);
4021 static DBusMessage *le_set_data_length(
4022 DBusConnection *conn, DBusMessage *msg,
4025 dbus_uint16_t max_tx_octets;
4026 dbus_uint16_t max_tx_time;
4027 struct btd_device *device = user_data;
4031 if (!dbus_message_get_args(msg, NULL,
4032 DBUS_TYPE_UINT16, &max_tx_octets,
4033 DBUS_TYPE_UINT16, &max_tx_time,
4034 DBUS_TYPE_INVALID)) {
4035 DBG("error in retrieving values");
4036 return btd_error_invalid_args(msg);
4039 if (device->bdaddr_type == BDADDR_BREDR)
4040 return btd_error_not_supported(msg);
4042 ba2str(&device->bdaddr, addr);
4044 DBG("Remote device address: %s", addr);
4045 DBG("Max tx octets: %u, Max tx time: %u",
4046 max_tx_octets, max_tx_time);
4048 status = btd_adapter_le_set_data_length(device->adapter,
4049 &device->bdaddr, max_tx_octets,
4053 return btd_error_failed(msg, "Unable to set le data length values");
4055 return dbus_message_new_method_return(msg);
4058 static DBusMessage *set_trusted_profile(DBusConnection *conn,
4059 DBusMessage *msg, void *data)
4061 struct btd_device *dev = data;
4062 dbus_bool_t profile_trusted;
4063 const char *pattern;
4065 uint32_t pbap = dev->trusted_profiles.pbap;
4066 uint32_t map = dev->trusted_profiles.map;
4067 uint32_t sap = dev->trusted_profiles.sap;
4068 uint32_t hfp_hs = dev->trusted_profiles.hfp_hs;
4069 uint32_t a2dp = dev->trusted_profiles.a2dp;
4071 if (!dbus_message_get_args(msg, NULL,
4072 DBUS_TYPE_STRING, &pattern,
4073 DBUS_TYPE_BOOLEAN, &profile_trusted,
4075 return btd_error_invalid_args(msg);
4077 DBG("Pattern : %s", pattern);
4078 uuid = bt_name2string(pattern);
4079 DBG("UUID : %s", uuid);
4080 DBG("profile Trusted : %d %d %d", dev->trusted_profiles.pbap,
4081 dev->trusted_profiles.map, dev->trusted_profiles.sap);
4082 DBG("profile Restricted : %d %d", dev->trusted_profiles.hfp_hs,
4083 dev->trusted_profiles.a2dp);
4084 if (g_strcmp0(uuid, OBEX_PBAP_UUID) == 0) {
4085 if (profile_trusted)
4086 pbap = SUPPORTED_TRUSTED;
4088 pbap = SUPPORTED_BLOCKED;
4089 } else if (g_strcmp0(uuid, OBEX_MAP_UUID) == 0) {
4090 if (profile_trusted)
4091 map = SUPPORTED_TRUSTED;
4093 map = SUPPORTED_BLOCKED;
4094 } else if (g_strcmp0(uuid, SAP_UUID) == 0) {
4095 if (profile_trusted)
4096 sap = SUPPORTED_TRUSTED;
4098 sap = SUPPORTED_BLOCKED;
4099 } else if (g_strcmp0(uuid, HFP_HS_UUID) == 0) {
4100 if (profile_trusted)
4101 hfp_hs = SUPPORTED_TRUSTED;
4103 hfp_hs = SUPPORTED_BLOCKED;
4104 } else if (g_strcmp0(uuid, A2DP_SINK_UUID) == 0) {
4105 if (profile_trusted)
4106 a2dp = SUPPORTED_TRUSTED;
4108 a2dp = SUPPORTED_BLOCKED;
4111 return btd_error_invalid_args(msg);
4115 btd_device_set_trusted_profiles(dev, pbap, map, sap, hfp_hs, a2dp);
4116 return dbus_message_new_method_return(msg);
4119 static DBusMessage *is_connected_profile(DBusConnection *conn, DBusMessage *msg,
4122 struct btd_device *dev = user_data;
4123 struct btd_service *service;
4124 btd_service_state_t state;
4125 const char *pattern;
4130 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
4132 return btd_error_invalid_args(msg);
4134 reply = dbus_message_new_method_return(msg);
4136 return btd_error_invalid_args(reply);
4138 uuid = bt_name2string(pattern);
4139 DBG("is_connected_profile_uuid : %s", uuid);
4140 service = btd_device_get_service(dev, uuid);
4142 if ((service == NULL) && (g_strcmp0(uuid, HFP_HS_UUID) == 0)) {
4143 DBG("HFP service is not found check for HSP service");
4144 service = btd_device_get_service(dev, HSP_HS_UUID);
4150 return btd_error_not_connected(msg);
4152 state = btd_service_get_state(service);
4153 DBG("Connected State : %d", state);
4155 if (state == BTD_SERVICE_STATE_CONNECTED)
4160 dbus_message_append_args(reply,
4161 DBUS_TYPE_BOOLEAN, &val,
4167 static DBusMessage *update_le_conn_parm(DBusConnection *conn, DBusMessage *msg,
4170 struct btd_device *device = user_data;
4173 struct le_conn_param param = {0, 0, 0, 0};
4174 uint32_t min, max, latency, to_multiplier;
4178 if (device == NULL) {
4179 error("device is NULL");
4180 return btd_error_invalid_args(msg);
4184 error("le is not supported");
4185 return btd_error_not_supported(msg);
4188 if (!device->gatt_connected || !device->attrib)
4189 return btd_error_not_connected(msg);
4191 io = g_attrib_get_channel(device->attrib);
4193 return btd_error_not_connected(msg);
4195 fd = g_io_channel_unix_get_fd(io);
4197 return btd_error_not_connected(msg);
4199 if (device_get_conn_update_state(device))
4200 return btd_error_in_progress(msg);
4202 device_set_conn_update_state(device, true);
4204 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &min,
4205 DBUS_TYPE_UINT32, &max,
4206 DBUS_TYPE_UINT32, &latency,
4207 DBUS_TYPE_UINT32, &to_multiplier,
4208 DBUS_TYPE_INVALID)) {
4209 error("Invalid args");
4210 return btd_error_invalid_args(msg);
4213 if (min > UINT16_MAX || max > UINT16_MAX ||
4214 latency > UINT16_MAX || to_multiplier > UINT16_MAX) {
4215 error("Invalid args");
4216 return btd_error_invalid_args(msg);
4218 param.min = (uint16_t)min;
4219 param.max = (uint16_t)max;
4220 param.latency = (uint16_t)latency;
4221 param.to_multiplier = (uint16_t)to_multiplier;
4223 if (setsockopt(fd, SOL_BLUETOOTH, BT_LE_CONN_PARAM,
4224 ¶m, sizeof(param)) < 0) {
4225 error("Can't Update LE conn param : %s (%d)",
4226 strerror(errno), errno);
4227 return btd_error_failed(msg, strerror(errno));
4230 return dbus_message_new_method_return(msg);
4233 static void device_request_att_mtu_reponse_cb(bool success, uint8_t att_ecode,
4236 struct btd_device *device = user_data;
4238 DBusMessageIter iter;
4241 if (!device->req_att_mtu)
4244 mtu = bt_gatt_client_get_mtu(device->client);
4248 err_if = ERROR_INTERFACE ".Failed";
4250 reply = dbus_message_new_error(device->req_att_mtu, err_if,
4251 "Request Att MTU failed");
4252 g_dbus_send_message(dbus_conn, reply);
4256 DBG("MTU exchange complete, with MTU: %u", mtu);
4258 reply = dbus_message_new_method_return(device->req_att_mtu);
4262 dbus_message_iter_init_append(reply, &iter);
4264 dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
4266 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
4268 g_dbus_send_message(dbus_conn, reply);
4270 dbus_message_unref(device->req_att_mtu);
4271 device->req_att_mtu = NULL;
4274 static DBusMessage *request_att_mtu(DBusConnection *conn, DBusMessage *msg,
4277 struct btd_device *device = user_data;
4282 if (device == NULL) {
4283 error("device is NULL");
4284 return btd_error_invalid_args(msg);
4288 error("le is not supported");
4289 return btd_error_not_supported(msg);
4292 if (!device->gatt_connected || !device->attrib)
4293 return btd_error_not_connected(msg);
4295 if (!dbus_message_get_args(msg, NULL,
4296 DBUS_TYPE_UINT16, &mtu,
4297 DBUS_TYPE_INVALID)) {
4298 error("Invalid args");
4299 return btd_error_invalid_args(msg);
4304 if (!bt_gatt_request_att_mtu(device->client, mtu,
4305 device_request_att_mtu_reponse_cb, device))
4306 return btd_error_failed(msg, "Unable to Request MTU");
4308 device->req_att_mtu = dbus_message_ref(msg);
4312 static DBusMessage *device_get_ida(DBusConnection *conn, DBusMessage *msg,
4315 struct btd_device *device = user_data;
4316 char device_idaddr[18] = { 0 };
4318 const gchar *id_address = device_idaddr;
4323 return btd_error_invalid_args(msg);
4326 error("It doesn't support LE");
4327 return btd_error_not_supported(msg);
4331 // There is the first RPA. So it's paired device.
4333 ba2str(device->rpa, device_idaddr);
4335 ba2str(&device->bdaddr, device_idaddr);
4336 } else if (device->bdaddr_type != BDADDR_LE_RANDOM) {
4337 // device->bdaddr is identity address.
4338 ba2str(&device->bdaddr, device_idaddr);
4339 } else if ((device->bdaddr.b[5] >> 6) == 0x01) {
4340 // RPA but it's not paired
4341 return btd_error_does_not_exist(msg);
4342 } else if ((device->bdaddr.b[5] >> 6) == 0x03) {
4343 // Static Random address
4344 ba2str(&device->bdaddr, device_idaddr);
4347 return btd_error_not_supported(msg);
4350 reply = dbus_message_new_method_return(msg);
4354 dbus_message_append_args(reply, DBUS_TYPE_STRING, &id_address,
4360 void device_set_conn_update_state(struct btd_device *device, bool state)
4365 device->pending_conn_update = state;
4368 bool device_get_conn_update_state(struct btd_device *device)
4370 return device->pending_conn_update;
4374 static const GDBusMethodTable device_methods[] = {
4375 { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, dev_disconnect) },
4376 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, dev_connect) },
4377 { GDBUS_ASYNC_METHOD("ConnectProfile", GDBUS_ARGS({ "UUID", "s" }),
4378 NULL, connect_profile) },
4379 { GDBUS_ASYNC_METHOD("DisconnectProfile", GDBUS_ARGS({ "UUID", "s" }),
4380 NULL, disconnect_profile) },
4381 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4382 { GDBUS_ASYNC_METHOD("DisconnectExtProfile",
4383 GDBUS_ARGS({ "profile", "o" }), NULL,
4384 disconnect_ext_profile) },
4385 { GDBUS_ASYNC_METHOD("Pair", GDBUS_ARGS({ "conn_type", "y" }), NULL,
4388 { GDBUS_ASYNC_METHOD("Pair", NULL, NULL, pair_device) },
4390 { GDBUS_METHOD("CancelPairing", NULL, NULL, cancel_pairing) },
4391 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4392 { GDBUS_ASYNC_METHOD("ConnectLE", GDBUS_ARGS({ "auto_connect", "b"}),
4393 NULL, connect_le) },
4394 { GDBUS_ASYNC_METHOD("DisconnectLE", NULL, NULL, disconnect_le) },
4395 { GDBUS_METHOD("IsConnectedProfile", GDBUS_ARGS({ "UUID", "s" }),
4396 GDBUS_ARGS({ "IsConnected", "b" }),
4397 is_connected_profile)},
4398 { GDBUS_METHOD("LeConnUpdate", GDBUS_ARGS({ "interval_min", "u" },
4399 { "interval_max", "u" }, { "latency", "u" },
4400 { "time_out", "u" }), NULL,
4401 update_le_conn_parm) },
4402 { GDBUS_ASYNC_METHOD("DiscoverServices", GDBUS_ARGS({ "pattern", "s" }),
4403 NULL, discover_services) },
4404 { GDBUS_METHOD("CancelDiscovery", NULL, NULL, cancel_discover) },
4405 { GDBUS_ASYNC_METHOD("ConnectIpsp", NULL, NULL, connect_ipsp) },
4406 { GDBUS_ASYNC_METHOD("DisconnectIpsp", NULL, NULL, disconnect_ipsp) },
4407 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4408 { GDBUS_METHOD("ConnectOtc", NULL, NULL, connect_otc) },
4409 { GDBUS_METHOD("DisconnectOtc", NULL, NULL, disconnect_otc) },
4410 { GDBUS_METHOD("ListenOtc", NULL, NULL, listen_otc) },
4412 { GDBUS_ASYNC_METHOD("LESetDataLength",
4413 GDBUS_ARGS({"max_tx_octets", "q" },
4414 { "max_tx_time", "q" }), NULL,
4415 le_set_data_length)},
4416 { GDBUS_ASYNC_METHOD("RequestAttMtu", GDBUS_ARGS({ "mtu", "q" }),
4417 GDBUS_ARGS({ "mtu", "q" }, { "status", "y"}),
4419 { GDBUS_METHOD("GetIDAddress", NULL, GDBUS_ARGS({ "IDAdress", "s" }),
4421 { GDBUS_METHOD("SetTrustedProfile",
4422 GDBUS_ARGS({ "uuid", "s"}, { "trusted", "b"}), NULL,
4423 set_trusted_profile) },
4428 static const GDBusPropertyTable device_properties[] = {
4429 { "Address", "s", dev_property_get_address },
4430 { "AddressType", "s", property_get_address_type },
4431 { "Name", "s", dev_property_get_name, NULL, dev_property_exists_name },
4432 { "Alias", "s", dev_property_get_alias, dev_property_set_alias },
4433 { "Class", "u", dev_property_get_class, NULL,
4434 dev_property_exists_class },
4435 { "Appearance", "q", dev_property_get_appearance, NULL,
4436 dev_property_exists_appearance },
4437 { "Icon", "s", dev_property_get_icon, NULL,
4438 dev_property_exists_icon },
4439 { "Paired", "b", dev_property_get_paired },
4440 { "Trusted", "b", dev_property_get_trusted, dev_property_set_trusted },
4441 { "Blocked", "b", dev_property_get_blocked, dev_property_set_blocked },
4442 { "LegacyPairing", "b", dev_property_get_legacy },
4443 { "RSSI", "n", dev_property_get_rssi, NULL, dev_property_exists_rssi },
4444 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4445 {"IsAliasSet", "b", dev_property_get_alias_set },
4446 { "Connected", "y", dev_property_get_connected },
4448 { "Connected", "b", dev_property_get_connected },
4450 { "UUIDs", "as", dev_property_get_uuids },
4451 { "Modalias", "s", dev_property_get_modalias, NULL,
4452 dev_property_exists_modalias },
4453 { "Adapter", "o", dev_property_get_adapter },
4454 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4455 /* To handle Failed Legacy Pairing when initiated from Remote device*/
4456 { "LegacyPaired", "b", dev_property_get_paired },
4457 { "LegacyManufacturerDataLen", "q", property_get_manufacturer_data_len },
4458 { "LegacyManufacturerData", "ay", property_get_manufacturer_data },
4459 { "GattConnected", "b", dev_property_get_gatt_connected },
4460 { "PayloadTimeout", "q", dev_property_get_payload},
4461 { "LastAddrType", "y", dev_property_get_last_addr_type},
4462 { "IpspConnected", "b", dev_property_get_ipsp_conn_state },
4463 { "IpspBtInterfaceInfo", "s", dev_property_get_ipsp_conn_bt_iface_name },
4464 { "AttMtu", "q", dev_property_get_att_mtu },
4465 { "TrustedProfiles", "u", dev_property_get_trusted_profiles},
4467 { "ManufacturerData", "a{qv}", dev_property_get_manufacturer_data,
4468 NULL, dev_property_manufacturer_data_exist },
4469 { "ServiceData", "a{sv}", dev_property_get_service_data,
4470 NULL, dev_property_service_data_exist },
4471 { "TxPower", "n", dev_property_get_tx_power, NULL,
4472 dev_property_exists_tx_power },
4473 { "ServicesResolved", "b", dev_property_get_svc_resolved, NULL, NULL },
4474 { "AdvertisingFlags", "ay", dev_property_get_flags, NULL,
4475 dev_property_flags_exist,
4476 G_DBUS_PROPERTY_FLAG_EXPERIMENTAL},
4477 { "AdvertisingData", "a{yv}", dev_property_get_advertising_data,
4478 NULL, dev_property_advertising_data_exist,
4479 G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
4483 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4484 static const GDBusSignalTable device_signals[] = {
4485 { GDBUS_SIGNAL("Disconnected",
4486 GDBUS_ARGS({ "bdaddr_type", "y" }, { "reason", "y" },
4487 { "name", "s" })) },
4488 { GDBUS_SIGNAL("DeviceConnected", GDBUS_ARGS({ "bdaddr_type", "y"})) },
4489 { GDBUS_SIGNAL("ProfileStateChanged",
4490 GDBUS_ARGS({ "profile", "s"}, {"state", "i"})) },
4491 { GDBUS_SIGNAL("AdvReport",
4492 GDBUS_ARGS({"Address","s"}, { "Address Type", "y" },
4493 { "Adv Type", "y"}, { "RSSI", "i"},
4494 { "AdvDataLen", "i"}, { "AdvData", "ay"})) },
4495 { GDBUS_SIGNAL("LEDataLengthChanged",
4496 GDBUS_ARGS({"max_tx_octets","q"},
4497 { "max_tx_time", "q" },
4498 { "max_rx_octets", "q"},
4499 { "max_rx_time", "q"}))},
4500 { GDBUS_SIGNAL("IpspStateChanged",
4501 GDBUS_ARGS({"connected","b"}, {"if_name","s"}))},
4502 { GDBUS_SIGNAL("OtcDisconnected", NULL)},
4503 { GDBUS_SIGNAL("AttMtuChanged",
4504 GDBUS_ARGS({"mtu", "q"})) },
4509 uint8_t btd_device_get_bdaddr_type(struct btd_device *dev)
4511 return dev->bdaddr_type;
4514 bool btd_device_is_connected(struct btd_device *dev)
4516 return dev->bredr_state.connected || dev->le_state.connected;
4519 void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type)
4521 struct bearer_state *state = get_state(dev, bdaddr_type);
4523 device_update_last_seen(dev, bdaddr_type);
4525 if (state->connected) {
4527 ba2str(&dev->bdaddr, addr);
4528 error("Device %s is already connected", addr);
4532 bacpy(&dev->conn_bdaddr, &dev->bdaddr);
4533 dev->conn_bdaddr_type = dev->bdaddr_type;
4535 /* If this is the first connection over this bearer */
4536 if (bdaddr_type == BDADDR_BREDR)
4537 device_set_bredr_support(dev);
4539 device_set_le_support(dev, bdaddr_type);
4541 state->connected = true;
4543 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
4544 if (dev->le_state.connected && dev->bredr_state.connected)
4547 g_dbus_emit_property_changed(dbus_conn, dev->path, DEVICE_INTERFACE,
4550 #ifdef TIZEN_FEATURE_BLUEZ_BATTERY_WATCH
4551 if (bdaddr_type == BDADDR_BREDR &&
4552 get_charging_state(dev->adapter) == WIRELESS_CHARGING) {
4553 int br_pkt_type = ACL_PTYPE_MASK |
4554 HCI_2DH1 | HCI_2DH3 | HCI_2DH5 |
4555 HCI_3DH1 | HCI_3DH3 | HCI_3DH5;
4557 DBG("During wireless charging... Change packet type");
4558 device_change_pkt_type(dev, (gpointer)br_pkt_type);
4560 #endif /* TIZEN_FEATURE_BLUEZ_BATTERY_WATCH */
4562 g_dbus_emit_signal(dbus_conn, dev->path,
4563 DEVICE_INTERFACE, "DeviceConnected",
4564 DBUS_TYPE_BYTE, &bdaddr_type,
4569 void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type)
4571 struct bearer_state *state = get_state(device, bdaddr_type);
4572 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4573 char *dev_name = device->name;
4576 if (!state->connected)
4579 state->connected = false;
4580 device->general_connect = FALSE;
4582 device_set_svc_refreshed(device, false);
4584 if (device->disconn_timer > 0) {
4585 g_source_remove(device->disconn_timer);
4586 device->disconn_timer = 0;
4589 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4590 if (device->browse) {
4591 struct browse_req *req = device->browse;
4593 if ((bdaddr_type == BDADDR_BREDR && req->search_uuid != 0) ||
4594 (bdaddr_type != BDADDR_BREDR && req->search_uuid == 0))
4595 device->browse = NULL;
4597 DBG("device->browse is for other link");
4601 while (device->disconnects) {
4602 DBusMessage *msg = device->disconnects->data;
4604 g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
4605 device->disconnects = g_slist_remove(device->disconnects, msg);
4606 dbus_message_unref(msg);
4609 if (state->paired && !state->bonded) {
4610 btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
4612 state->paired = false;
4614 /* report change only if both bearers are unpaired */
4615 if (!device->bredr_state.paired && !device->le_state.paired)
4616 g_dbus_emit_property_changed(dbus_conn, device->path,
4622 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
4623 if (device->bredr_state.connected || device->le_state.connected)
4626 g_dbus_emit_property_changed(dbus_conn, device->path,
4627 DEVICE_INTERFACE, "Connected");
4629 g_dbus_emit_signal(dbus_conn, device->path,
4630 DEVICE_INTERFACE, "Disconnected",
4631 DBUS_TYPE_BYTE, &bdaddr_type,
4632 DBUS_TYPE_BYTE, &device->disc_reason,
4633 DBUS_TYPE_STRING, &dev_name,
4638 guint device_add_disconnect_watch(struct btd_device *device,
4639 disconnect_watch watch, void *user_data,
4640 GDestroyNotify destroy)
4642 struct btd_disconnect_data *data;
4643 static guint id = 0;
4645 data = g_new0(struct btd_disconnect_data, 1);
4647 data->watch = watch;
4648 data->user_data = user_data;
4649 data->destroy = destroy;
4651 device->watches = g_slist_append(device->watches, data);
4656 void device_remove_disconnect_watch(struct btd_device *device, guint id)
4660 for (l = device->watches; l; l = l->next) {
4661 struct btd_disconnect_data *data = l->data;
4663 if (data->id == id) {
4664 device->watches = g_slist_remove(device->watches,
4667 data->destroy(data->user_data);
4674 static char *load_cached_name(struct btd_device *device, const char *local,
4677 char filename[PATH_MAX];
4682 if (device_address_is_private(device))
4685 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
4687 key_file = g_key_file_new();
4689 if (!g_key_file_load_from_file(key_file, filename, 0, NULL))
4692 str = g_key_file_get_string(key_file, "General", "Name", NULL);
4695 if (len > HCI_MAX_NAME_LENGTH)
4696 str[HCI_MAX_NAME_LENGTH] = '\0';
4700 g_key_file_free(key_file);
4705 static struct csrk_info *load_csrk(GKeyFile *key_file, const char *group)
4707 struct csrk_info *csrk;
4711 str = g_key_file_get_string(key_file, group, "Key", NULL);
4715 csrk = g_new0(struct csrk_info, 1);
4717 for (i = 0; i < 16; i++) {
4718 if (sscanf(str + (i * 2), "%2hhx", &csrk->key[i]) != 1)
4723 * In case of older storage this will return 0 which is fine since it
4724 * didn't support signing at that point the counter should never have
4727 csrk->counter = g_key_file_get_integer(key_file, group, "Counter",
4739 static void load_services(struct btd_device *device, char **uuids)
4743 for (uuid = uuids; *uuid; uuid++) {
4744 if (g_slist_find_custom(device->uuids, *uuid, bt_uuid_strcmp))
4747 device->uuids = g_slist_insert_sorted(device->uuids,
4755 static void convert_info(struct btd_device *device, GKeyFile *key_file)
4757 char filename[PATH_MAX];
4758 char adapter_addr[18];
4759 char device_addr[18];
4764 /* Load device profile list from legacy properties */
4765 uuids = g_key_file_get_string_list(key_file, "General", "SDPServices",
4768 load_services(device, uuids);
4770 uuids = g_key_file_get_string_list(key_file, "General", "GATTServices",
4773 load_services(device, uuids);
4778 /* Remove old entries so they are not loaded again */
4779 g_key_file_remove_key(key_file, "General", "SDPServices", NULL);
4780 g_key_file_remove_key(key_file, "General", "GATTServices", NULL);
4782 ba2str(btd_adapter_get_address(device->adapter), adapter_addr);
4783 ba2str(&device->bdaddr, device_addr);
4784 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
4787 str = g_key_file_to_data(key_file, &length, NULL);
4788 g_file_set_contents(filename, str, length, NULL);
4791 store_device_info(device);
4794 static void load_info(struct btd_device *device, const char *local,
4795 const char *peer, GKeyFile *key_file)
4798 gboolean store_needed = FALSE;
4801 int source, vendor, product, version;
4803 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4804 gboolean svc_change_regd;
4805 char buf[DEV_MAX_MANUFACTURER_DATA_LEN] = { 0, };
4807 /* Load device name from storage info file, if that fails fall back to
4810 str = g_key_file_get_string(key_file, "General", "Name", NULL);
4812 str = load_cached_name(device, local, peer);
4814 store_needed = TRUE;
4818 strcpy(device->name, str);
4823 device->alias = g_key_file_get_string(key_file, "General", "Alias",
4827 str = g_key_file_get_string(key_file, "General", "Class", NULL);
4831 if (sscanf(str, "%x", &class) == 1)
4832 device->class = class;
4836 /* Load appearance */
4837 str = g_key_file_get_string(key_file, "General", "Appearance", NULL);
4839 device->appearance = strtol(str, NULL, 16);
4843 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4844 /* Load RPA Resolution Support value */
4845 device->rpa_res_support = g_key_file_get_integer(key_file,
4846 "General", "RPAResSupport", NULL);
4848 str = g_key_file_get_string(key_file, "General", "LegacyManufacturerDataLen", NULL);
4850 device->manufacturer_data_len = strtol(str, NULL, 10);
4853 if (0 > device->manufacturer_data_len) {
4854 error("Invalid manufacturer_data_len: %d",
4855 device->manufacturer_data_len);
4856 device->manufacturer_data_len = 0;
4859 str = g_key_file_get_string(key_file, "General", "LegacyManufacturerData", NULL);
4861 if (device->manufacturer_data_len < DEV_MAX_MANUFACTURER_DATA_LEN) {
4862 load_manufacturer_data_2digit(str,
4863 device->manufacturer_data_len, buf);
4864 device->manufacturer_data = g_memdup(buf,
4865 device->manufacturer_data_len);
4871 str = g_key_file_get_string(key_file, "General", "IdentityAddress",
4875 device->rpa = g_malloc0(sizeof(bdaddr_t));
4876 bacpy(device->rpa, &device->bdaddr);
4877 str2ba(str, &device->bdaddr);
4882 /* Load device technology */
4883 techno = g_key_file_get_string_list(key_file, "General",
4884 "SupportedTechnologies", NULL, NULL);
4888 for (t = techno; *t; t++) {
4889 if (g_str_equal(*t, "BR/EDR"))
4890 device->bredr = true;
4891 else if (g_str_equal(*t, "LE"))
4894 error("Unknown device technology");
4898 device->bdaddr_type = BDADDR_BREDR;
4900 str = g_key_file_get_string(key_file, "General",
4901 "AddressType", NULL);
4903 if (str && g_str_equal(str, "public"))
4904 device->bdaddr_type = BDADDR_LE_PUBLIC;
4905 else if (str && g_str_equal(str, "static"))
4906 device->bdaddr_type = BDADDR_LE_RANDOM;
4908 error("Unknown LE device technology");
4912 device->local_csrk = load_csrk(key_file, "LocalSignatureKey");
4913 device->remote_csrk = load_csrk(key_file, "RemoteSignatureKey");
4920 device->trusted = g_key_file_get_boolean(key_file, "General",
4923 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4924 /* Load Trusted Profiles*/
4925 int trusted_profiles = g_key_file_get_integer(key_file, "General",
4926 "TrustedProfiles", NULL);
4927 DBG("Loading TrustedProfiles %d", trusted_profiles);
4928 device->trusted_profiles.pbap = ((trusted_profiles &
4929 (PROFILE_SUPPORTED << PBAP_SHIFT_OFFSET)) >> PBAP_SHIFT_OFFSET);
4930 device->trusted_profiles.map = ((trusted_profiles &
4931 (PROFILE_SUPPORTED << MAP_SHIFT_OFFSET)) >> MAP_SHIFT_OFFSET);
4932 device->trusted_profiles.sap = ((trusted_profiles &
4933 (PROFILE_SUPPORTED << SAP_SHIFT_OFFSET)) >> SAP_SHIFT_OFFSET);
4934 device->trusted_profiles.hfp_hs = ((trusted_profiles &
4935 (PROFILE_SUPPORTED << HFP_HS_SHIFT_OFFSET)) >> HFP_HS_SHIFT_OFFSET);
4936 device->trusted_profiles.a2dp = ((trusted_profiles &
4937 (PROFILE_SUPPORTED << A2DP_SHIFT_OFFSET)) >> A2DP_SHIFT_OFFSET);
4941 /* Load device blocked */
4942 blocked = g_key_file_get_boolean(key_file, "General", "Blocked", NULL);
4944 device_block(device, FALSE);
4946 /* Load device profile list */
4947 uuids = g_key_file_get_string_list(key_file, "General", "Services",
4950 load_services(device, uuids);
4952 /* Discovered services restored from storage */
4953 device->bredr_state.svc_resolved = true;
4956 /* Load device id */
4957 source = g_key_file_get_integer(key_file, "DeviceID", "Source", NULL);
4959 vendor = g_key_file_get_integer(key_file, "DeviceID",
4962 product = g_key_file_get_integer(key_file, "DeviceID",
4965 version = g_key_file_get_integer(key_file, "DeviceID",
4968 btd_device_set_pnpid(device, source, vendor, product, version);
4971 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4972 /* Load Service changed Registered flag */
4973 svc_change_regd = g_key_file_get_boolean(key_file, "Att",
4974 "SvcChangeRegd", NULL);
4976 bt_att_set_svc_changed_indication_registered(device->att,
4981 store_device_info(device);
4984 static void load_att_info(struct btd_device *device, const char *local,
4987 char filename[PATH_MAX];
4989 char *prim_uuid, *str;
4990 char **groups, **handle, *service_uuid;
4991 struct gatt_primary *prim;
4996 sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
4997 prim_uuid = bt_uuid2string(&uuid);
4999 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes", local,
5002 key_file = g_key_file_new();
5003 g_key_file_load_from_file(key_file, filename, 0, NULL);
5004 groups = g_key_file_get_groups(key_file, NULL);
5006 for (handle = groups; *handle; handle++) {
5010 str = g_key_file_get_string(key_file, *handle, "UUID", NULL);
5014 uuid_ok = g_str_equal(str, prim_uuid);
5020 str = g_key_file_get_string(key_file, *handle, "Value", NULL);
5024 end = g_key_file_get_integer(key_file, *handle,
5025 "EndGroupHandle", NULL);
5031 prim = g_new0(struct gatt_primary, 1);
5032 prim->range.start = atoi(*handle);
5033 prim->range.end = end;
5035 switch (strlen(str)) {
5037 uuid.type = SDP_UUID16;
5038 sscanf(str, "%04hx", &uuid.value.uuid16);
5041 uuid.type = SDP_UUID32;
5042 sscanf(str, "%08x", &uuid.value.uuid32);
5045 uuid.type = SDP_UUID128;
5046 memset(tmp, 0, sizeof(tmp));
5047 for (i = 0; i < 16; i++) {
5048 memcpy(tmp, str + (i * 2), 2);
5049 uuid.value.uuid128.data[i] =
5050 (uint8_t) strtol(tmp, NULL, 16);
5059 service_uuid = bt_uuid2string(&uuid);
5060 memcpy(prim->uuid, service_uuid, MAX_LEN_UUID_STR);
5064 device->primaries = g_slist_append(device->primaries, prim);
5068 g_key_file_free(key_file);
5072 static void device_register_primaries(struct btd_device *device,
5073 GSList *prim_list, int psm)
5075 device->primaries = g_slist_concat(device->primaries, prim_list);
5078 static void add_primary(struct gatt_db_attribute *attr, void *user_data)
5080 GSList **new_services = user_data;
5081 struct gatt_primary *prim;
5084 prim = g_new0(struct gatt_primary, 1);
5086 DBG("Failed to allocate gatt_primary structure");
5090 gatt_db_attribute_get_service_handles(attr, &prim->range.start,
5092 gatt_db_attribute_get_service_uuid(attr, &uuid);
5093 bt_uuid_to_string(&uuid, prim->uuid, sizeof(prim->uuid));
5095 *new_services = g_slist_append(*new_services, prim);
5098 static void load_desc_value(struct gatt_db_attribute *attrib,
5099 int err, void *user_data)
5102 warn("loading descriptor value to db failed");
5105 static ssize_t str2val(const char *str, uint8_t *val, size_t len)
5107 const char *pos = str;
5110 for (i = 0; i < len; i++) {
5111 if (sscanf(pos, "%2hhx", &val[i]) != 1)
5119 static int load_desc(char *handle, char *value,
5120 struct gatt_db_attribute *service)
5122 char uuid_str[MAX_LEN_UUID_STR];
5123 struct gatt_db_attribute *att;
5124 uint16_t handle_int;
5126 bt_uuid_t uuid, ext_uuid;
5128 if (sscanf(handle, "%04hx", &handle_int) != 1)
5131 /* Check if there is any value stored, otherwise it is just the UUID */
5132 if (sscanf(value, "%04hx:%s", &val, uuid_str) != 2) {
5133 if (sscanf(value, "%s", uuid_str) != 1)
5138 DBG("loading descriptor handle: 0x%04x, value: 0x%04x, value uuid: %s",
5139 handle_int, val, uuid_str);
5141 bt_string_to_uuid(&uuid, uuid_str);
5142 bt_uuid16_create(&ext_uuid, GATT_CHARAC_EXT_PROPER_UUID);
5144 /* If it is CEP then it must contain the value */
5145 if (!bt_uuid_cmp(&uuid, &ext_uuid) && !val) {
5146 warn("cannot load CEP descriptor without value");
5150 att = gatt_db_service_insert_descriptor(service, handle_int, &uuid,
5151 0, NULL, NULL, NULL);
5152 if (!att || gatt_db_attribute_get_handle(att) != handle_int) {
5153 warn("loading descriptor to db failed");
5158 if (!gatt_db_attribute_write(att, 0, (uint8_t *)&val,
5159 sizeof(val), 0, NULL,
5160 load_desc_value, NULL))
5167 static int load_chrc(char *handle, char *value,
5168 struct gatt_db_attribute *service)
5170 uint16_t properties, value_handle, handle_int;
5171 char uuid_str[MAX_LEN_UUID_STR];
5172 struct gatt_db_attribute *att;
5178 if (sscanf(handle, "%04hx", &handle_int) != 1)
5181 /* Check if there is any value stored */
5182 if (sscanf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hx:%32s:%s",
5183 &value_handle, &properties, val_str, uuid_str) != 4) {
5184 if (sscanf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hx:%s",
5185 &value_handle, &properties, uuid_str) != 3)
5189 val_len = str2val(val_str, val, sizeof(val));
5191 bt_string_to_uuid(&uuid, uuid_str);
5193 /* Log debug message. */
5194 DBG("loading characteristic handle: 0x%04x, value handle: 0x%04x,"
5195 " properties 0x%04x value: %s uuid: %s",
5196 handle_int, value_handle, properties,
5197 val_len ? val_str : "", uuid_str);
5199 att = gatt_db_service_insert_characteristic(service, value_handle,
5200 &uuid, 0, properties,
5202 if (!att || gatt_db_attribute_get_handle(att) != value_handle) {
5203 warn("loading characteristic to db failed");
5208 if (!gatt_db_attribute_write(att, 0, val, val_len, 0, NULL,
5209 load_desc_value, NULL))
5216 static int load_incl(struct gatt_db *db, char *handle, char *value,
5217 struct gatt_db_attribute *service)
5219 char uuid_str[MAX_LEN_UUID_STR];
5220 struct gatt_db_attribute *att;
5221 uint16_t start, end;
5223 if (sscanf(handle, "%04hx", &start) != 1)
5226 if (sscanf(value, GATT_INCLUDE_UUID_STR ":%04hx:%04hx:%s", &start, &end,
5230 /* Log debug message. */
5231 DBG("loading included service: 0x%04x, end: 0x%04x, uuid: %s", start,
5234 att = gatt_db_get_attribute(db, start);
5236 warn("loading included service to db failed - no such service");
5240 att = gatt_db_service_add_included(service, att);
5242 warn("loading included service to db failed");
5249 static int load_service(struct gatt_db *db, char *handle, char *value)
5251 struct gatt_db_attribute *att;
5252 uint16_t start, end;
5253 char type[MAX_LEN_UUID_STR], uuid_str[MAX_LEN_UUID_STR];
5257 if (sscanf(handle, "%04hx", &start) != 1)
5260 if (sscanf(value, "%[^:]:%04hx:%s", type, &end, uuid_str) != 3)
5263 if (g_str_equal(type, GATT_PRIM_SVC_UUID_STR))
5265 else if (g_str_equal(type, GATT_SND_SVC_UUID_STR))
5270 bt_string_to_uuid(&uuid, uuid_str);
5272 /* Log debug message. */
5273 DBG("loading service: 0x%04x, end: 0x%04x, uuid: %s",
5274 start, end, uuid_str);
5276 att = gatt_db_insert_service(db, start, &uuid, primary,
5279 error("Unable load service into db!");
5286 static int load_gatt_db_impl(GKeyFile *key_file, char **keys,
5289 struct gatt_db_attribute *current_service;
5290 char **handle, *value, type[MAX_LEN_UUID_STR];
5293 /* first load service definitions */
5294 for (handle = keys; *handle; handle++) {
5295 value = g_key_file_get_string(key_file, "Attributes", *handle,
5298 if (sscanf(value, "%[^:]:", type) != 1) {
5299 warn("Missing Type in attribute definition");
5304 if (g_str_equal(type, GATT_PRIM_SVC_UUID_STR) ||
5305 g_str_equal(type, GATT_SND_SVC_UUID_STR)) {
5306 ret = load_service(db, *handle, value);
5316 current_service = NULL;
5317 /* then fill them with data*/
5318 for (handle = keys; *handle; handle++) {
5319 value = g_key_file_get_string(key_file, "Attributes", *handle,
5322 if (sscanf(value, "%[^:]:", type) != 1) {
5323 warn("Missing Type in attribute definition");
5328 if (g_str_equal(type, GATT_PRIM_SVC_UUID_STR) ||
5329 g_str_equal(type, GATT_SND_SVC_UUID_STR)) {
5331 uint16_t start, end;
5334 char uuid_str[MAX_LEN_UUID_STR];
5336 if (sscanf(*handle, "%04hx", &tmp) != 1) {
5337 warn("Unable to parse attribute handle");
5342 if (current_service)
5343 gatt_db_service_set_active(current_service,
5346 current_service = gatt_db_get_attribute(db, tmp);
5348 gatt_db_attribute_get_service_data(current_service,
5352 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
5353 } else if (g_str_equal(type, GATT_INCLUDE_UUID_STR)) {
5354 ret = load_incl(db, *handle, value, current_service);
5355 } else if (g_str_equal(type, GATT_CHARAC_UUID_STR)) {
5356 ret = load_chrc(*handle, value, current_service);
5358 ret = load_desc(*handle, value, current_service);
5368 if (current_service)
5369 gatt_db_service_set_active(current_service, true);
5374 static void load_gatt_db(struct btd_device *device, const char *local,
5377 char **keys, filename[PATH_MAX];
5380 if (!gatt_cache_is_enabled(device))
5383 DBG("Restoring %s gatt database from file", peer);
5385 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
5387 key_file = g_key_file_new();
5388 g_key_file_load_from_file(key_file, filename, 0, NULL);
5389 keys = g_key_file_get_keys(key_file, "Attributes", NULL, NULL);
5392 warn("No cache for %s", peer);
5393 g_key_file_free(key_file);
5397 if (load_gatt_db_impl(key_file, keys, device->db))
5398 warn("Unable to load gatt db from file for %s", peer);
5401 g_key_file_free(key_file);
5403 g_slist_free_full(device->primaries, g_free);
5404 device->primaries = NULL;
5405 gatt_db_foreach_service(device->db, NULL, add_primary,
5406 &device->primaries);
5409 static void device_add_uuids(struct btd_device *device, GSList *uuids)
5412 bool changed = false;
5414 for (l = uuids; l != NULL; l = g_slist_next(l)) {
5415 GSList *match = g_slist_find_custom(device->uuids, l->data,
5421 device->uuids = g_slist_insert_sorted(device->uuids,
5427 g_dbus_emit_property_changed(dbus_conn, device->path,
5428 DEVICE_INTERFACE, "UUIDs");
5431 static bool device_match_profile(struct btd_device *device,
5432 struct btd_profile *profile,
5435 if (profile->remote_uuid == NULL)
5438 if (g_slist_find_custom(uuids, profile->remote_uuid,
5439 bt_uuid_strcmp) == NULL) {
5440 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
5441 if (strcmp(profile->name, "hid-device") == 0)
5450 static void add_gatt_service(struct gatt_db_attribute *attr, void *user_data)
5452 struct btd_device *device = user_data;
5453 struct btd_service *service;
5454 struct btd_profile *profile;
5456 char uuid_str[MAX_LEN_UUID_STR];
5459 gatt_db_attribute_get_service_uuid(attr, &uuid);
5460 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
5462 /* Check if service was already probed */
5463 l = find_service_with_uuid(device->services, uuid_str);
5467 /* Add UUID and probe service */
5468 btd_device_add_uuid(device, uuid_str);
5470 /* Check if service was probed */
5471 l = find_service_with_uuid(device->services, uuid_str);
5476 /* Mark service as active to skip discovering it again */
5477 gatt_db_service_set_active(attr, true);
5480 profile = btd_service_get_profile(service);
5482 /* Claim attributes of internal profiles */
5483 if (!profile->external) {
5484 /* Mark the service as claimed by the existing profile. */
5485 gatt_db_service_set_claimed(attr, true);
5488 /* Notify driver about the new connection */
5489 service_accept(service);
5492 static void device_add_gatt_services(struct btd_device *device)
5496 ba2str(&device->bdaddr, addr);
5498 if (device->blocked) {
5499 DBG("Skipping profiles for blocked device %s", addr);
5503 gatt_db_foreach_service(device->db, NULL, add_gatt_service, device);
5506 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5507 static void accept_gatt_service(struct gatt_db_attribute *attr, void *user_data)
5509 struct btd_device *device = user_data;
5512 char uuid_str[MAX_LEN_UUID_STR];
5514 gatt_db_attribute_get_service_uuid(attr, &uuid);
5515 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
5517 l = find_service_with_uuid(device->services, uuid_str);
5521 service_accept(l->data);
5525 static void device_accept_gatt_profiles(struct btd_device *device)
5527 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
5530 for (l = device->services; l != NULL; l = g_slist_next(l))
5531 service_accept(l->data);
5533 gatt_db_foreach_service(device->db, NULL, accept_gatt_service, device);
5537 static void device_remove_gatt_service(struct btd_device *device,
5538 struct gatt_db_attribute *attr)
5540 struct btd_service *service;
5542 char uuid_str[MAX_LEN_UUID_STR];
5545 gatt_db_attribute_get_service_uuid(attr, &uuid);
5546 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
5548 l = find_service_with_uuid(device->services, uuid_str);
5553 device->services = g_slist_delete_link(device->services, l);
5554 device->pending = g_slist_remove(device->pending, service);
5555 service_remove(service);
5558 static gboolean gatt_services_changed(gpointer user_data)
5560 struct btd_device *device = user_data;
5562 store_gatt_db(device);
5567 static void gatt_service_added(struct gatt_db_attribute *attr, void *user_data)
5569 struct btd_device *device = user_data;
5570 GSList *new_service = NULL;
5571 uint16_t start, end;
5573 if (!bt_gatt_client_is_ready(device->client))
5576 gatt_db_attribute_get_service_data(attr, &start, &end, NULL, NULL);
5578 DBG("start: 0x%04x, end: 0x%04x", start, end);
5581 * TODO: Remove the primaries list entirely once all profiles use
5584 add_primary(attr, &new_service);
5588 device_register_primaries(device, new_service, -1);
5590 add_gatt_service(attr, device);
5592 btd_gatt_client_service_added(device->client_dbus, attr);
5594 gatt_services_changed(device);
5597 static gint prim_attr_cmp(gconstpointer a, gconstpointer b)
5599 const struct gatt_primary *prim = a;
5600 const struct gatt_db_attribute *attr = b;
5601 uint16_t start, end;
5603 gatt_db_attribute_get_service_handles(attr, &start, &end);
5605 return !(prim->range.start == start && prim->range.end == end);
5608 static gint prim_uuid_cmp(gconstpointer a, gconstpointer b)
5610 const struct gatt_primary *prim = a;
5611 const char *uuid = b;
5613 return bt_uuid_strcmp(prim->uuid, uuid);
5616 static void gatt_service_removed(struct gatt_db_attribute *attr,
5619 struct btd_device *device = user_data;
5621 struct gatt_primary *prim;
5622 uint16_t start, end;
5625 * NOTE: shared/gatt-client clears the database in case of failure. This
5626 * triggers the service_removed callback for all affected services.
5627 * Hence, this function will be called in the following cases:
5629 * 1. When a GATT service gets removed due to "Service Changed".
5631 * 2. When a GATT service gets removed when the database get cleared
5632 * upon disconnection with a non-bonded device.
5634 * 3. When a GATT service gets removed when the database get cleared
5635 * by shared/gatt-client when its initialization procedure fails,
5636 * e.g. due to an ATT protocol error or an unexpected disconnect.
5637 * In this case the gatt-client will not be ready.
5640 gatt_db_attribute_get_service_handles(attr, &start, &end);
5642 DBG("start: 0x%04x, end: 0x%04x", start, end);
5644 /* Remove the corresponding gatt_primary */
5645 l = g_slist_find_custom(device->primaries, attr, prim_attr_cmp);
5650 device->primaries = g_slist_delete_link(device->primaries, l);
5653 * Remove the corresponding UUIDs entry and profile, only if this is
5654 * the last service with this UUID.
5656 l = g_slist_find_custom(device->uuids, prim->uuid, bt_uuid_strcmp);
5658 if (l && !g_slist_find_custom(device->primaries, prim->uuid,
5661 * If this happend since the db was cleared for a non-bonded
5662 * device, then don't remove the btd_service just yet. We do
5663 * this so that we can avoid re-probing the profile if the same
5664 * GATT service is found on the device on re-connection.
5665 * However, if the device is marked as temporary, then we
5668 if (device->client || device->temporary == TRUE)
5669 device_remove_gatt_service(device, attr);
5672 device->uuids = g_slist_delete_link(device->uuids, l);
5673 g_dbus_emit_property_changed(dbus_conn, device->path,
5674 DEVICE_INTERFACE, "UUIDs");
5679 store_device_info(device);
5681 btd_gatt_client_service_removed(device->client_dbus, attr);
5683 gatt_services_changed(device);
5686 static struct btd_device *device_new(struct btd_adapter *adapter,
5687 const char *address)
5690 struct btd_device *device;
5691 const char *adapter_path = adapter_get_path(adapter);
5693 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
5694 DBG("address %s", address);
5697 device = g_try_malloc0(sizeof(struct btd_device));
5701 device->tx_power = 127;
5703 device->db = gatt_db_new();
5709 memset(device->ad_flags, INVALID_FLAGS, sizeof(device->ad_flags));
5711 device->ad = bt_ad_new();
5713 device_free(device);
5717 address_up = g_ascii_strup(address, -1);
5718 device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up);
5719 g_strdelimit(device->path, ":", '_');
5722 str2ba(address, &device->bdaddr);
5724 device->client_dbus = btd_gatt_client_new(device);
5725 if (!device->client_dbus) {
5726 error("Failed to create btd_gatt_client");
5727 device_free(device);
5731 DBG("Creating device %s", device->path);
5733 if (g_dbus_register_interface(dbus_conn,
5734 device->path, DEVICE_INTERFACE,
5735 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5736 device_methods, device_signals,
5738 device_methods, NULL,
5740 device_properties, device,
5741 device_free) == FALSE) {
5742 error("Unable to register device interface for %s", address);
5743 device_free(device);
5747 device->adapter = adapter;
5748 device->temporary = true;
5750 device->db_id = gatt_db_register(device->db, gatt_service_added,
5751 gatt_service_removed, device, NULL);
5753 return btd_device_ref(device);
5756 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5757 void device_print_addr(struct btd_device *dev)
5762 ba2str(&dev->bdaddr, ida);
5765 ba2str(dev->rpa, rpa);
5767 DBG("IDA %s [%d] : RPA [%s], BREDR [%d], LE [%d]",
5768 ida, dev->bdaddr_type, rpa,
5769 dev->bredr ? 1 : 0, dev->le ? 1 : 0);
5771 DBG("ADDR %s [%d] : BREDR [%d], LE [%d]",
5772 ida, dev->bdaddr_type,
5773 dev->bredr ? 1 : 0, dev->le ? 1 : 0);
5778 struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
5779 const char *address, GKeyFile *key_file)
5781 struct btd_device *device;
5782 const char *src_dir;
5784 DBG("address %s", address);
5786 device = device_new(adapter, address);
5790 convert_info(device, key_file);
5792 src_dir = btd_adapter_get_storage_dir(adapter);
5794 load_info(device, src_dir, address, key_file);
5795 load_att_info(device, src_dir, address);
5800 struct btd_device *device_create(struct btd_adapter *adapter,
5801 const bdaddr_t *bdaddr, uint8_t bdaddr_type)
5803 struct btd_device *device;
5807 ba2str(bdaddr, dst);
5810 device = device_new(adapter, dst);
5814 device->bdaddr_type = bdaddr_type;
5816 if (bdaddr_type == BDADDR_BREDR)
5817 device->bredr = true;
5821 str = load_cached_name(device, btd_adapter_get_storage_dir(adapter),
5824 strcpy(device->name, str);
5831 char *btd_device_get_storage_path(struct btd_device *device,
5832 const char *filename)
5836 if (device_address_is_private(device)) {
5837 warn("Refusing storage path for private addressed device %s",
5842 ba2str(&device->bdaddr, dstaddr);
5844 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5846 ba2str(device->rpa, dstaddr);
5850 return g_strdup_printf(STORAGEDIR "/%s/%s",
5851 btd_adapter_get_storage_dir(device->adapter),
5854 return g_strdup_printf(STORAGEDIR "/%s/%s/%s",
5855 btd_adapter_get_storage_dir(device->adapter),
5859 void btd_device_device_set_name(struct btd_device *device, const char *name)
5861 if (strncmp(name, device->name, MAX_NAME_LENGTH) == 0)
5864 DBG("%s %s", device->path, name);
5866 strncpy(device->name, name, MAX_NAME_LENGTH);
5868 store_device_info(device);
5870 g_dbus_emit_property_changed(dbus_conn, device->path,
5871 DEVICE_INTERFACE, "Name");
5873 if (device->alias != NULL)
5876 g_dbus_emit_property_changed(dbus_conn, device->path,
5877 DEVICE_INTERFACE, "Alias");
5880 void device_get_name(struct btd_device *device, char *name, size_t len)
5882 if (name != NULL && len > 0) {
5883 strncpy(name, device->name, len - 1);
5884 name[len - 1] = '\0';
5888 bool device_name_known(struct btd_device *device)
5890 return device->name[0] != '\0';
5893 void device_set_class(struct btd_device *device, uint32_t class)
5895 if (device->class == class)
5898 DBG("%s 0x%06X", device->path, class);
5900 device->class = class;
5902 store_device_info(device);
5904 g_dbus_emit_property_changed(dbus_conn, device->path,
5905 DEVICE_INTERFACE, "Class");
5906 g_dbus_emit_property_changed(dbus_conn, device->path,
5907 DEVICE_INTERFACE, "Icon");
5910 void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
5911 uint8_t bdaddr_type)
5913 if (!bacmp(bdaddr, &device->bdaddr) &&
5914 bdaddr_type == device->bdaddr_type)
5917 /* Since this function is only used for LE SMP Identity
5918 * Resolving purposes we can now assume LE is supported.
5922 bacpy(&device->bdaddr, bdaddr);
5923 device->bdaddr_type = bdaddr_type;
5925 store_device_info(device);
5927 g_dbus_emit_property_changed(dbus_conn, device->path,
5928 DEVICE_INTERFACE, "Address");
5929 g_dbus_emit_property_changed(dbus_conn, device->path,
5930 DEVICE_INTERFACE, "AddressType");
5933 void device_set_bredr_support(struct btd_device *device)
5935 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5939 ba2str(device->rpa, addr_str);
5940 error("Cannot set bredr support to RPA device [%s]", addr_str);
5944 if (device->bdaddr_type == BDADDR_LE_RANDOM) {
5945 ba2str(&device->bdaddr, addr_str);
5946 error("Cannot set bredr support to LE random device [%s]",
5955 device->bredr = true;
5956 store_device_info(device);
5959 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5960 void device_set_rpa(struct btd_device *device, const bdaddr_t *rpa)
5962 if (device->rpa == NULL) {
5963 device->rpa = g_malloc0(sizeof(bdaddr_t));
5964 bacpy(device->rpa, rpa);
5966 error("RPA is already set");
5969 void device_set_irk_value(struct btd_device *device, const uint8_t *val)
5971 memcpy(&device->irk_val, val, sizeof(device->irk_val));
5975 void device_set_le_support(struct btd_device *device, uint8_t bdaddr_type)
5981 device->bdaddr_type = bdaddr_type;
5983 store_device_info(device);
5986 void device_update_last_seen(struct btd_device *device, uint8_t bdaddr_type)
5988 if (bdaddr_type == BDADDR_BREDR)
5989 device->bredr_seen = time(NULL);
5991 device->le_seen = time(NULL);
5994 /* It is possible that we have two device objects for the same device in
5995 * case it has first been discovered over BR/EDR and has a private
5996 * address when discovered over LE for the first time. In such a case we
5997 * need to inherit critical values from the duplicate so that we don't
5998 * ovewrite them when writing to storage. The next time bluetoothd
5999 * starts the device will show up as a single instance.
6001 void device_merge_duplicate(struct btd_device *dev, struct btd_device *dup)
6007 dev->bredr = dup->bredr;
6009 dev->trusted = dup->trusted;
6010 dev->blocked = dup->blocked;
6012 for (l = dup->uuids; l; l = g_slist_next(l))
6013 dev->uuids = g_slist_append(dev->uuids, g_strdup(l->data));
6015 if (dev->name[0] == '\0')
6016 strcpy(dev->name, dup->name);
6019 dev->alias = g_strdup(dup->alias);
6021 dev->class = dup->class;
6023 dev->vendor_src = dup->vendor_src;
6024 dev->vendor = dup->vendor;
6025 dev->product = dup->product;
6026 dev->version = dup->version;
6029 uint32_t btd_device_get_class(struct btd_device *device)
6031 return device->class;
6034 uint16_t btd_device_get_vendor(struct btd_device *device)
6036 return device->vendor;
6039 uint16_t btd_device_get_vendor_src(struct btd_device *device)
6041 return device->vendor_src;
6044 uint16_t btd_device_get_product(struct btd_device *device)
6046 return device->product;
6049 uint16_t btd_device_get_version(struct btd_device *device)
6051 return device->version;
6054 static void delete_folder_tree(const char *dirname)
6057 struct dirent *entry;
6058 char filename[PATH_MAX];
6060 dir = opendir(dirname);
6064 while ((entry = readdir(dir)) != NULL) {
6065 if (g_str_equal(entry->d_name, ".") ||
6066 g_str_equal(entry->d_name, ".."))
6069 if (entry->d_type == DT_UNKNOWN)
6070 entry->d_type = util_get_dt(dirname, entry->d_name);
6072 snprintf(filename, PATH_MAX, "%s/%s", dirname, entry->d_name);
6074 if (entry->d_type == DT_DIR)
6075 delete_folder_tree(filename);
6084 static void device_remove_stored(struct btd_device *device)
6086 char device_addr[18];
6087 char filename[PATH_MAX];
6092 if (device->bredr_state.bonded) {
6093 device->bredr_state.bonded = false;
6094 btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
6098 if (device->le_state.bonded) {
6099 device->le_state.bonded = false;
6100 btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
6101 device->bdaddr_type);
6104 device->bredr_state.paired = false;
6105 device->le_state.paired = false;
6107 if (device->blocked)
6108 device_unblock(device, TRUE, FALSE);
6110 ba2str(&device->bdaddr, device_addr);
6112 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6114 ba2str(device->rpa, device_addr);
6117 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s",
6118 btd_adapter_get_storage_dir(device->adapter),
6120 delete_folder_tree(filename);
6122 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
6123 btd_adapter_get_storage_dir(device->adapter),
6126 key_file = g_key_file_new();
6127 g_key_file_load_from_file(key_file, filename, 0, NULL);
6128 g_key_file_remove_group(key_file, "ServiceRecords", NULL);
6130 data = g_key_file_to_data(key_file, &length, NULL);
6132 create_file(filename, S_IRUSR | S_IWUSR);
6133 g_file_set_contents(filename, data, length, NULL);
6137 g_key_file_free(key_file);
6140 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6141 void device_unpair(struct btd_device *device, gboolean remove_stored)
6144 DBG("Unpairing device %s", device->path);
6146 if (device->bonding) {
6149 if (device->bredr_state.connected)
6150 status = MGMT_STATUS_DISCONNECTED;
6152 status = MGMT_STATUS_CONNECT_FAILED;
6154 device_cancel_bonding(device, status);
6158 browse_request_cancel(device->browse);
6161 // while (device->services != NULL) {
6162 // struct btd_service *service = device->services->data;
6164 // device->services = g_slist_remove(device->services, service);
6165 // service_remove(service);
6168 g_slist_free(device->pending);
6169 device->pending = NULL;
6171 if (btd_device_is_connected(device))
6172 disconnect_all(device);
6174 if (device->store_id > 0) {
6175 g_source_remove(device->store_id);
6176 device->store_id = 0;
6179 store_device_info_cb(device);
6183 device_remove_stored(device);
6185 gatt_db_clear(device->db);
6188 bacpy(&device->bdaddr, device->rpa);
6189 device->bdaddr_type = BDADDR_LE_RANDOM;
6191 g_free(device->rpa);
6195 device->bredr_state.paired = 0;
6196 device->le_state.paired = 0;
6197 device->bredr_state.svc_resolved = false;
6198 device->trusted = false;
6199 device->trusted_profiles.pbap = SHOW_AUTHORIZATION;
6200 device->trusted_profiles.map = SHOW_AUTHORIZATION;
6201 device->trusted_profiles.sap = SHOW_AUTHORIZATION;
6202 device->trusted_profiles.hfp_hs = SUPPORTED_TRUSTED;
6203 device->trusted_profiles.a2dp = SUPPORTED_TRUSTED;
6204 if (device->alias != NULL) {
6205 /* Remove alias name because
6206 * In UG if we rename and then unpair device and
6207 * initiates connection without scanning then paired
6208 * list will have alias name as first preference is
6209 * given to alias name.
6211 DBG("Freeing device alias name");
6212 g_free(device->alias);
6213 device->alias = NULL;
6215 g_dbus_emit_property_changed(dbus_conn, device->path,
6216 DEVICE_INTERFACE, "Paired");
6217 // btd_device_unref(device);
6221 void device_remove_stored_folder(struct btd_device *device)
6223 const bdaddr_t *src = btd_adapter_get_address(device->adapter);
6224 char adapter_addr[18];
6225 char device_addr[18];
6226 char filename[PATH_MAX];
6228 ba2str(src, adapter_addr);
6229 ba2str(&device->bdaddr, device_addr);
6231 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s", adapter_addr,
6234 delete_folder_tree(filename);
6238 void device_remove(struct btd_device *device, gboolean remove_stored)
6240 DBG("Removing device %s", device->path);
6242 if (device->bonding) {
6245 if (device->bredr_state.connected)
6246 status = MGMT_STATUS_DISCONNECTED;
6248 status = MGMT_STATUS_CONNECT_FAILED;
6250 device_cancel_bonding(device, status);
6254 browse_request_cancel(device->browse);
6256 while (device->services != NULL) {
6257 struct btd_service *service = device->services->data;
6259 device->services = g_slist_remove(device->services, service);
6260 service_remove(service);
6263 g_slist_free(device->pending);
6264 device->pending = NULL;
6266 if (btd_device_is_connected(device)) {
6267 if (device->disconn_timer > 0)
6268 g_source_remove(device->disconn_timer);
6269 disconnect_all(device);
6272 if (device->store_id > 0) {
6273 g_source_remove(device->store_id);
6274 device->store_id = 0;
6277 store_device_info_cb(device);
6281 device_remove_stored(device);
6283 btd_device_unref(device);
6286 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6287 int device_rpa_cmp(gconstpointer a, gconstpointer b)
6289 const struct btd_device *device = a;
6290 const char *address = b;
6296 ba2str(device->rpa, addr);
6298 return strcasecmp(addr, address);
6301 int device_addr_cmp(gconstpointer a, gconstpointer b)
6303 const struct btd_device *device = a;
6304 const bdaddr_t *bdaddr = b;
6306 return bacmp(&device->bdaddr, bdaddr);
6309 int device_rpa_ida_cmp(gconstpointer a, gconstpointer b)
6311 const struct btd_device *device = a;
6312 const char *address = b;
6315 if (!device->rpa || device->le == false)
6318 ba2str(&device->bdaddr, addr);
6319 return strcasecmp(addr, address);
6323 int device_address_cmp(gconstpointer a, gconstpointer b)
6325 const struct btd_device *device = a;
6326 const char *address = b;
6329 ba2str(&device->bdaddr, addr);
6330 return strcasecmp(addr, address);
6333 int device_bdaddr_cmp(gconstpointer a, gconstpointer b)
6335 const struct btd_device *device = a;
6336 const bdaddr_t *bdaddr = b;
6338 return bacmp(&device->bdaddr, bdaddr);
6341 static bool addr_is_public(uint8_t addr_type)
6343 if (addr_type == BDADDR_BREDR || addr_type == BDADDR_LE_PUBLIC)
6349 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6350 int device_addr_type_strict_cmp(gconstpointer a, gconstpointer b)
6352 const struct btd_device *dev = a;
6353 const struct device_addr_type *addr = b;
6356 cmp = bacmp(&dev->bdaddr, &addr->bdaddr);
6358 if (addr->bdaddr_type == BDADDR_BREDR) {
6368 if (cmp && dev->rpa && addr->bdaddr_type == BDADDR_LE_RANDOM &&
6369 (addr->bdaddr.b[5] >> 6) == 0x01)
6370 return bacmp(dev->rpa, &addr->bdaddr);
6372 if (addr->bdaddr_type != dev->bdaddr_type)
6379 int device_addr_type_cmp(gconstpointer a, gconstpointer b)
6381 const struct btd_device *dev = a;
6382 const struct device_addr_type *addr = b;
6385 cmp = bacmp(&dev->bdaddr, &addr->bdaddr);
6388 * Address matches and both old and new are public addresses
6389 * (doesn't matter whether LE or BR/EDR, then consider this a
6392 if (!cmp && addr_is_public(addr->bdaddr_type) &&
6393 addr_is_public(dev->bdaddr_type))
6394 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6396 if (dev->rpa && addr->bdaddr_type == BDADDR_BREDR) {
6399 ba2str(&dev->bdaddr, addr_str);
6400 DBG("Don't match. LE Only device [%s]", addr_str);
6409 if (addr->bdaddr_type == BDADDR_BREDR) {
6419 if (addr->bdaddr_type != dev->bdaddr_type) {
6420 if (addr->bdaddr_type == dev->conn_bdaddr_type)
6421 return bacmp(&dev->conn_bdaddr, &addr->bdaddr);
6428 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6429 #ifdef TIZEN_FEATURE_BLUEZ_BATTERY_WATCH
6430 void device_change_pkt_type(gpointer data, gpointer user_data)
6432 int pkt_type = (int)user_data;
6433 struct btd_device *device = data;
6434 struct hci_conn_info_req *cr;
6435 set_conn_ptype_cp cp;
6440 /* Change a packet type only for Phone device */
6441 if ((device->class & 0x00001F00) >> 8 != 0x02)
6444 if (!device->bredr_state.connected)
6447 hdev = hci_open_dev(0);
6449 error("Cannot open hdev");
6453 cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info));
6455 error("Out of memory");
6458 cr->type = ACL_LINK;
6459 bacpy(&cr->bdaddr, &device->bdaddr);
6461 err = ioctl(hdev, HCIGETCONNINFO, cr);
6463 error("Fail to get HCIGETCOINFO");
6465 hci_close_dev(hdev);
6469 cp.handle = cr->conn_info->handle;
6471 cp.pkt_type = cpu_to_le16((uint16_t)pkt_type);
6473 ba2str(&device->bdaddr, addr);
6474 DBG("Handle %d, Addr %s", cp.handle, addr);
6475 DBG("Send Change pkt type request : 0x%X", pkt_type);
6477 if (hci_send_cmd(hdev, OGF_LINK_CTL, OCF_SET_CONN_PTYPE,
6478 SET_CONN_PTYPE_CP_SIZE, &cp) < 0) {
6479 error("hci_send_cmd is failed");
6480 hci_close_dev(hdev);
6484 hci_close_dev(hdev);
6487 #endif /* TIZEN_FEATURE_BLUEZ_BATTERY_WATCH */
6490 static gboolean record_has_uuid(const sdp_record_t *rec,
6491 const char *profile_uuid)
6495 for (pat = rec->pattern; pat != NULL; pat = pat->next) {
6499 uuid = bt_uuid2string(pat->data);
6503 ret = strcasecmp(uuid, profile_uuid);
6514 GSList *btd_device_get_uuids(struct btd_device *device)
6516 return device->uuids;
6520 struct btd_device *dev;
6524 static struct btd_service *probe_service(struct btd_device *device,
6525 struct btd_profile *profile,
6529 struct btd_service *service;
6531 if (profile->device_probe == NULL)
6534 if (!device_match_profile(device, profile, uuids))
6537 l = find_service_with_profile(device->services, profile);
6541 service = service_create(device, profile);
6543 if (service_probe(service)) {
6544 btd_service_unref(service);
6548 /* Only set auto connect if profile has set the flag and can really
6549 * accept connections.
6551 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
6552 if (profile->auto_connect && profile->accept)
6553 device_set_auto_connect(device, TRUE);
6559 static void dev_probe(struct btd_profile *p, void *user_data)
6561 struct probe_data *d = user_data;
6562 struct btd_service *service;
6564 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6565 if (find_service_with_profile(d->dev->services, p)) {
6566 DBG("%s is already probed.(UUID:%s)", p->name, p->remote_uuid);
6571 service = probe_service(d->dev, p, d->uuids);
6575 d->dev->services = g_slist_append(d->dev->services, service);
6578 void device_probe_profile(gpointer a, gpointer b)
6580 struct btd_device *device = a;
6581 struct btd_profile *profile = b;
6582 struct btd_service *service;
6584 service = probe_service(device, profile, device->uuids);
6588 device->services = g_slist_append(device->services, service);
6590 if (!profile->auto_connect || !device->general_connect)
6593 device->pending = g_slist_append(device->pending, service);
6595 if (g_slist_length(device->pending) == 1)
6596 connect_next(device);
6599 void device_remove_profile(gpointer a, gpointer b)
6601 struct btd_device *device = a;
6602 struct btd_profile *profile = b;
6603 struct btd_service *service;
6606 l = find_service_with_profile(device->services, profile);
6607 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
6609 if (g_strcmp0(profile->local_uuid , HID_DEVICE_UUID) == 0) {
6610 l = find_service_with_uuid(device->services,
6617 if (btd_service_get_state(service) ==
6618 BTD_SERVICE_STATE_CONNECTED) {
6620 err = btd_service_disconnect(service);
6622 error("error: %s", strerror(-err));
6633 device->services = g_slist_delete_link(device->services, l);
6634 device->pending = g_slist_remove(device->pending, service);
6635 service_remove(service);
6638 void device_probe_profiles(struct btd_device *device, GSList *uuids)
6640 struct probe_data d = { device, uuids };
6643 ba2str(&device->bdaddr, addr);
6645 if (device->blocked) {
6646 DBG("Skipping profiles for blocked device %s", addr);
6650 DBG("Probing profiles for device %s", addr);
6652 btd_profile_foreach(dev_probe, &d);
6655 device_add_uuids(device, uuids);
6658 static void store_sdp_record(GKeyFile *key_file, sdp_record_t *rec)
6660 char handle_str[11];
6665 sprintf(handle_str, "0x%8.8X", rec->handle);
6667 if (sdp_gen_record_pdu(rec, &buf) < 0)
6670 size = buf.data_size;
6672 str = g_malloc0(size*2+1);
6674 for (i = 0; i < size; i++)
6675 sprintf(str + (i * 2), "%02X", buf.data[i]);
6677 g_key_file_set_string(key_file, "ServiceRecords", handle_str, str);
6683 static void store_primaries_from_sdp_record(GKeyFile *key_file,
6687 char *att_uuid, *prim_uuid;
6688 uint16_t start = 0, end = 0, psm = 0;
6689 char handle[6], uuid_str[33];
6692 sdp_uuid16_create(&uuid, ATT_UUID);
6693 att_uuid = bt_uuid2string(&uuid);
6695 sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
6696 prim_uuid = bt_uuid2string(&uuid);
6698 if (!record_has_uuid(rec, att_uuid))
6701 if (!gatt_parse_record(rec, &uuid, &psm, &start, &end))
6704 sprintf(handle, "%hu", start);
6705 switch (uuid.type) {
6707 sprintf(uuid_str, "%4.4X", uuid.value.uuid16);
6710 sprintf(uuid_str, "%8.8X", uuid.value.uuid32);
6713 for (i = 0; i < 16; i++)
6714 sprintf(uuid_str + (i * 2), "%2.2X",
6715 uuid.value.uuid128.data[i]);
6721 g_key_file_set_string(key_file, handle, "UUID", prim_uuid);
6722 g_key_file_set_string(key_file, handle, "Value", uuid_str);
6723 g_key_file_set_integer(key_file, handle, "EndGroupHandle", end);
6730 static int rec_cmp(const void *a, const void *b)
6732 const sdp_record_t *r1 = a;
6733 const sdp_record_t *r2 = b;
6735 return r1->handle - r2->handle;
6738 static int update_record(struct browse_req *req, const char *uuid,
6743 /* Check for duplicates */
6744 if (sdp_list_find(req->records, rec, rec_cmp))
6748 req->records = sdp_list_append(req->records, sdp_copy_record(rec));
6750 /* Check if UUID is duplicated */
6751 l = g_slist_find_custom(req->device->uuids, uuid, bt_uuid_strcmp);
6753 l = g_slist_find_custom(req->profiles_added, uuid,
6757 req->profiles_added = g_slist_append(req->profiles_added,
6764 static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
6766 struct btd_device *device = req->device;
6768 char srcaddr[18], dstaddr[18];
6769 char sdp_file[PATH_MAX];
6770 char att_file[PATH_MAX];
6771 GKeyFile *sdp_key_file;
6772 GKeyFile *att_key_file;
6776 ba2str(btd_adapter_get_address(device->adapter), srcaddr);
6777 ba2str(&device->bdaddr, dstaddr);
6779 snprintf(sdp_file, PATH_MAX, STORAGEDIR "/%s/cache/%s", srcaddr,
6782 sdp_key_file = g_key_file_new();
6783 g_key_file_load_from_file(sdp_key_file, sdp_file, 0, NULL);
6785 snprintf(att_file, PATH_MAX, STORAGEDIR "/%s/%s/attributes", srcaddr,
6788 att_key_file = g_key_file_new();
6789 g_key_file_load_from_file(att_key_file, att_file, 0, NULL);
6791 for (seq = recs; seq; seq = seq->next) {
6792 sdp_record_t *rec = (sdp_record_t *) seq->data;
6793 sdp_list_t *svcclass = NULL;
6799 if (sdp_get_service_classes(rec, &svcclass) < 0)
6802 /* Check for empty service classes list */
6803 if (svcclass == NULL) {
6804 DBG("Skipping record with no service classes");
6808 /* Extract the first element and skip the remainning */
6809 profile_uuid = bt_uuid2string(svcclass->data);
6810 if (!profile_uuid) {
6811 sdp_list_free(svcclass, free);
6815 if (bt_uuid_strcmp(profile_uuid, PNP_UUID) == 0) {
6816 uint16_t source, vendor, product, version;
6819 pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID_SOURCE);
6820 source = pdlist ? pdlist->val.uint16 : 0x0000;
6822 pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
6823 vendor = pdlist ? pdlist->val.uint16 : 0x0000;
6825 pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
6826 product = pdlist ? pdlist->val.uint16 : 0x0000;
6828 pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
6829 version = pdlist ? pdlist->val.uint16 : 0x0000;
6831 if (source || vendor || product || version)
6832 btd_device_set_pnpid(device, source, vendor,
6836 if (update_record(req, profile_uuid, rec) < 0)
6840 store_sdp_record(sdp_key_file, rec);
6843 store_primaries_from_sdp_record(att_key_file, rec);
6847 sdp_list_free(svcclass, free);
6851 data = g_key_file_to_data(sdp_key_file, &length, NULL);
6853 create_file(sdp_file, S_IRUSR | S_IWUSR);
6854 g_file_set_contents(sdp_file, data, length, NULL);
6858 g_key_file_free(sdp_key_file);
6862 data = g_key_file_to_data(att_key_file, &length, NULL);
6864 create_file(att_file, S_IRUSR | S_IWUSR);
6865 g_file_set_contents(att_file, data, length, NULL);
6869 g_key_file_free(att_key_file);
6873 static int primary_cmp(gconstpointer a, gconstpointer b)
6875 return memcmp(a, b, sizeof(struct gatt_primary));
6878 static void update_gatt_uuids(struct browse_req *req, GSList *current,
6883 /* Added Profiles */
6884 for (l = found; l; l = g_slist_next(l)) {
6885 struct gatt_primary *prim = l->data;
6888 lmatch = g_slist_find_custom(current, prim, primary_cmp);
6893 req->profiles_added = g_slist_append(req->profiles_added,
6894 g_strdup(prim->uuid));
6896 DBG("UUID Added: %s", prim->uuid);
6900 static GSList *device_services_from_record(struct btd_device *device,
6903 GSList *l, *prim_list = NULL;
6907 sdp_uuid16_create(&proto_uuid, ATT_UUID);
6908 att_uuid = bt_uuid2string(&proto_uuid);
6910 for (l = profiles; l; l = l->next) {
6911 const char *profile_uuid = l->data;
6912 const sdp_record_t *rec;
6913 struct gatt_primary *prim;
6914 uint16_t start = 0, end = 0, psm = 0;
6917 rec = btd_device_get_record(device, profile_uuid);
6921 if (!record_has_uuid(rec, att_uuid))
6924 if (!gatt_parse_record(rec, &prim_uuid, &psm, &start, &end))
6927 prim = g_new0(struct gatt_primary, 1);
6928 prim->range.start = start;
6929 prim->range.end = end;
6930 sdp_uuid2strn(&prim_uuid, prim->uuid, sizeof(prim->uuid));
6932 prim_list = g_slist_append(prim_list, prim);
6940 static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
6942 struct browse_req *req = user_data;
6943 struct btd_device *device = req->device;
6947 ba2str(&device->bdaddr, addr);
6950 error("%s: error updating services: %s (%d)",
6951 addr, strerror(-err), -err);
6955 update_bredr_services(req, recs);
6957 if (device->tmp_records)
6958 sdp_list_free(device->tmp_records,
6959 (sdp_free_func_t) sdp_record_free);
6961 device->tmp_records = req->records;
6962 req->records = NULL;
6964 if (!req->profiles_added) {
6965 DBG("%s: No service update", addr);
6969 primaries = device_services_from_record(device, req->profiles_added);
6971 device_register_primaries(device, primaries, ATT_PSM);
6974 * TODO: The btd_service instances for GATT services need to be
6975 * initialized with the service handles. Eventually this code should
6976 * perform ATT protocol service discovery over the ATT PSM to obtain
6977 * the full list of services and populate a client-role gatt_db over
6980 device_probe_profiles(device, req->profiles_added);
6982 /* Propagate services changes */
6983 g_dbus_emit_property_changed(dbus_conn, req->device->path,
6984 DEVICE_INTERFACE, "UUIDs");
6987 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6991 /* since no new services are found, UUID signal is not emitted,
6992 ** so send a reply to the framework with the existing services */
6993 if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
6994 "DiscoverServices"))
6995 discover_services_reply(req, err, device->tmp_records);
7000 device_svc_resolved(device, BROWSE_SDP, BDADDR_BREDR, err);
7003 static void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
7005 struct browse_req *req = user_data;
7006 struct btd_device *device = req->device;
7007 struct btd_adapter *adapter = device->adapter;
7010 /* If we have a valid response and req->search_uuid == 2, then L2CAP
7011 * UUID & PNP searching was successful -- we are done */
7012 if (err < 0 || (req->search_uuid == 2 && req->records)) {
7013 if (err == -ECONNRESET && req->reconnect_attempt < 1) {
7015 req->reconnect_attempt++;
7020 update_bredr_services(req, recs);
7022 /* Search for mandatory uuids */
7023 if (uuid_list[req->search_uuid]) {
7024 sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
7025 bt_search_service(btd_adapter_get_address(adapter),
7026 &device->bdaddr, &uuid,
7027 browse_cb, user_data, NULL,
7033 search_cb(recs, err, user_data);
7036 static bool device_get_auto_connect(struct btd_device *device)
7038 if (device->disable_auto_connect)
7041 return device->auto_connect;
7044 static void disconnect_gatt_service(gpointer data, gpointer user_data)
7046 struct btd_service *service = data;
7047 struct btd_profile *profile = btd_service_get_profile(service);
7049 /* Ignore if profile cannot accept connections */
7050 if (!profile->accept)
7053 btd_service_disconnect(service);
7056 static void att_disconnected_cb(int err, void *user_data)
7058 struct btd_device *device = user_data;
7065 DBG("%s (%d)", strerror(err), err);
7067 g_slist_foreach(device->services, disconnect_gatt_service, NULL);
7069 btd_gatt_client_disconnected(device->client_dbus);
7071 if (!device_get_auto_connect(device)) {
7072 DBG("Automatic connection disabled");
7077 * Keep scanning/re-connection active if disconnection reason
7078 * is connection timeout, remote user terminated connection or local
7079 * initiated disconnection.
7081 if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
7082 adapter_connect_list_add(device->adapter, device);
7085 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7086 device_set_gatt_connected(device, FALSE);
7088 attio_cleanup(device);
7091 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7092 static void att_mtu_changed(uint16_t mtu, void *user_data)
7094 struct btd_device *device = user_data;
7096 DBG("att mtu changed %d", mtu);
7098 g_dbus_emit_signal(dbus_conn, device->path,
7099 DEVICE_INTERFACE, "AttMtuChanged",
7100 DBUS_TYPE_UINT16, &mtu,
7105 static void register_gatt_services(struct btd_device *device)
7107 struct browse_req *req = device->browse;
7108 GSList *services = NULL;
7110 if (!bt_gatt_client_is_ready(device->client))
7114 * TODO: Remove the primaries list entirely once all profiles use
7117 gatt_db_foreach_service(device->db, NULL, add_primary, &services);
7119 btd_device_set_temporary(device, false);
7121 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7123 if (req->search_uuid)
7124 DBG("browse req. is for SDP. Ignore it.");
7126 update_gatt_uuids(req, device->primaries, services);
7130 update_gatt_uuids(req, device->primaries, services);
7133 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
7134 /* do not delete existing primary list,
7135 * just append the new primary uuids,
7136 * the list will be modifed when service changed
7137 * indication is received during connection */
7138 g_slist_free_full(device->primaries, g_free);
7139 device->primaries = NULL;
7142 device_register_primaries(device, services, -1);
7144 device_add_gatt_services(device);
7147 static void gatt_client_init(struct btd_device *device);
7149 static void gatt_client_ready_cb(bool success, uint8_t att_ecode,
7152 struct btd_device *device = user_data;
7154 DBG("status: %s, error: %u", success ? "success" : "failed", att_ecode);
7157 device_svc_resolved(device, BROWSE_GATT, device->bdaddr_type,
7162 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
7163 /* Register the services after setting the client is ready
7164 * and exporting all the services and characteristics paths.
7166 register_gatt_services(device);
7169 btd_gatt_client_ready(device->client_dbus);
7170 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7171 register_gatt_services(device);
7174 device_svc_resolved(device, BROWSE_GATT, device->bdaddr_type, 0);
7176 store_gatt_db(device);
7178 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7179 if (device->name[0] == '\0') {
7181 name = bt_gatt_client_get_gap_device_name(device->client);
7183 strncpy(device->name, name, MAX_NAME_LENGTH);
7188 static void gatt_client_service_changed(uint16_t start_handle,
7189 uint16_t end_handle,
7192 DBG("start 0x%04x, end: 0x%04x", start_handle, end_handle);
7195 static void gatt_debug(const char *str, void *user_data)
7200 static void gatt_client_init(struct btd_device *device)
7202 gatt_client_cleanup(device);
7204 if (!device->connect && !main_opts.reverse_discovery) {
7205 DBG("Reverse service discovery disabled: skipping GATT client");
7209 device->client = bt_gatt_client_new(device->db, device->att,
7211 if (!device->client) {
7212 DBG("Failed to initialize");
7216 bt_gatt_client_set_debug(device->client, gatt_debug, NULL, NULL);
7219 * Notify notify existing service about the new connection so they can
7220 * react to notifications while discovering services
7222 device_accept_gatt_profiles(device);
7224 device->gatt_ready_id = bt_gatt_client_ready_register(device->client,
7225 gatt_client_ready_cb,
7227 if (!device->gatt_ready_id) {
7228 DBG("Failed to register GATT ready callback");
7229 gatt_client_cleanup(device);
7233 if (!bt_gatt_client_set_service_changed(device->client,
7234 gatt_client_service_changed,
7236 DBG("Failed to set service changed handler");
7237 gatt_client_cleanup(device);
7241 btd_gatt_client_connected(device->client_dbus);
7244 static void gatt_server_init(struct btd_device *device,
7245 struct btd_gatt_database *database)
7247 struct gatt_db *db = btd_gatt_database_get_db(database);
7250 error("No local GATT database exists for this adapter");
7254 gatt_server_cleanup(device);
7256 device->server = bt_gatt_server_new(db, device->att, device->att_mtu,
7257 main_opts.key_size);
7258 if (!device->server) {
7259 error("Failed to initialize bt_gatt_server");
7263 bt_att_set_enc_key_size(device->att, device->ltk_enc_size);
7265 bt_gatt_server_set_debug(device->server, gatt_debug, NULL, NULL);
7267 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7268 if (!bt_gatt_server_set_mtu_changed(device->server,
7271 DBG("Failed to set mtu changed handler");
7277 static bool local_counter(uint32_t *sign_cnt, void *user_data)
7279 struct btd_device *dev = user_data;
7281 if (!dev->local_csrk)
7284 *sign_cnt = dev->local_csrk->counter++;
7286 store_device_info(dev);
7291 static bool remote_counter(uint32_t *sign_cnt, void *user_data)
7293 struct btd_device *dev = user_data;
7295 if (!dev->remote_csrk || *sign_cnt < dev->remote_csrk->counter)
7298 dev->remote_csrk->counter = *sign_cnt;
7300 store_device_info(dev);
7305 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7306 static bool load_svc_change_indication_status(struct btd_device *device, const char *local,
7309 char filename[PATH_MAX];
7311 gboolean svc_change_regd = false;
7312 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
7314 key_file = g_key_file_new();
7315 if (!g_key_file_load_from_file(key_file, filename, 0, NULL))
7318 /* Load Service changed Registered flag */
7319 svc_change_regd = g_key_file_get_boolean(key_file, "Att",
7320 "SvcChangeRegd", NULL);
7321 bt_att_set_svc_changed_indication_registered(device->att,
7326 g_key_file_free(key_file);
7328 return svc_change_regd;
7332 bool device_attach_att(struct btd_device *dev, GIOChannel *io)
7334 GError *gerr = NULL;
7336 BtIOSecLevel sec_level;
7339 struct btd_gatt_database *database;
7340 const bdaddr_t *dst;
7342 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7343 uint8_t dst_type = BDADDR_BREDR;
7345 const bdaddr_t *src;
7348 bt_io_get(io, &gerr, BT_IO_OPT_SEC_LEVEL, &sec_level,
7349 BT_IO_OPT_IMTU, &mtu,
7350 BT_IO_OPT_CID, &cid,
7351 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7352 BT_IO_OPT_DEST_TYPE, &dst_type,
7357 error("bt_io_get: %s", gerr->message);
7362 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
7363 if (sec_level == BT_IO_SEC_LOW && dev->le_state.paired) {
7364 DBG("Elevating security level since LTK is available");
7366 sec_level = BT_IO_SEC_MEDIUM;
7367 bt_io_set(io, &gerr, BT_IO_OPT_SEC_LEVEL, sec_level,
7370 error("bt_io_set: %s", gerr->message);
7377 dev->att_mtu = MIN(mtu, main_opts.gatt_mtu);
7378 attrib = g_attrib_new(io,
7379 cid == ATT_CID ? BT_ATT_DEFAULT_LE_MTU : dev->att_mtu,
7382 error("Unable to create new GAttrib instance");
7386 dev->attrib = attrib;
7387 dev->att = g_attrib_get_att(attrib);
7389 bt_att_ref(dev->att);
7391 dev->att_disconn_id = bt_att_register_disconnect(dev->att,
7392 att_disconnected_cb, dev, NULL);
7393 bt_att_set_close_on_unref(dev->att, true);
7395 if (dev->local_csrk)
7396 bt_att_set_local_key(dev->att, dev->local_csrk->key,
7397 local_counter, dev);
7399 if (dev->remote_csrk)
7400 bt_att_set_remote_key(dev->att, dev->remote_csrk->key,
7401 remote_counter, dev);
7403 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7404 if (dst_type != BDADDR_BREDR && device_get_rpa_exist(dev) == true) {
7405 bt_att_set_remote_addr(dev->att,
7406 device_get_rpa(dev), BDADDR_LE_RANDOM);
7408 bt_att_set_remote_addr(dev->att,
7409 &dev->bdaddr, dev->bdaddr_type);
7413 database = btd_adapter_get_database(dev->adapter);
7415 dst = device_get_address(dev);
7416 ba2str(dst, dstaddr);
7418 if (gatt_db_isempty(dev->db))
7419 load_gatt_db(dev, btd_adapter_get_storage_dir(dev->adapter),
7422 gatt_client_init(dev);
7423 gatt_server_init(dev, database);
7426 * Remove the device from the connect_list and give the passive
7427 * scanning another chance to be restarted in case there are
7428 * other devices in the connect_list.
7430 adapter_connect_list_remove(dev->adapter, dev);
7432 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7433 src = btd_adapter_get_address(dev->adapter);
7434 ba2str(src, srcaddr);
7436 /* load the service changed indication status on connection */
7437 load_svc_change_indication_status(dev, srcaddr, dstaddr);
7443 static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
7445 struct btd_device *device = user_data;
7450 g_io_channel_unref(device->att_io);
7451 device->att_io = NULL;
7454 DBG("%s", gerr->message);
7456 if (g_error_matches(gerr, BT_IO_ERROR, ECONNABORTED))
7459 if (device_get_auto_connect(device)) {
7460 DBG("Enabling automatic connections");
7461 adapter_connect_list_add(device->adapter, device);
7465 browse_request_complete(device->browse,
7467 device->bdaddr_type,
7470 err = -ECONNABORTED;
7474 if (!device_attach_att(device, io))
7477 if (!device->bonding)
7480 if (device->bonding->agent)
7481 io_cap = agent_get_io_capability(device->bonding->agent);
7483 io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
7485 err = adapter_create_bonding(device->adapter, &device->bdaddr,
7486 device->bdaddr_type, io_cap);
7488 if (device->bonding && err < 0) {
7489 reply = btd_error_failed(device->bonding->msg, strerror(-err));
7490 g_dbus_send_message(dbus_conn, reply);
7491 bonding_request_cancel(device->bonding);
7492 bonding_request_free(device->bonding);
7496 device_browse_gatt(device, NULL);
7498 if (device->connect) {
7500 reply = btd_error_failed(device->connect,
7503 reply = dbus_message_new_method_return(device->connect);
7505 g_dbus_send_message(dbus_conn, reply);
7506 dbus_message_unref(device->connect);
7507 device->connect = NULL;
7511 int device_connect_le(struct btd_device *dev)
7513 struct btd_adapter *adapter = dev->adapter;
7514 BtIOSecLevel sec_level;
7516 GError *gerr = NULL;
7519 /* There is one connection attempt going on */
7523 ba2str(&dev->bdaddr, addr);
7525 DBG("Connection attempt to: %s", addr);
7527 if (dev->le_state.paired)
7528 sec_level = BT_IO_SEC_MEDIUM;
7530 sec_level = BT_IO_SEC_LOW;
7533 * This connection will help us catch any PDUs that comes before
7536 io = bt_io_connect(att_connect_cb, dev, NULL, &gerr,
7537 BT_IO_OPT_SOURCE_BDADDR,
7538 btd_adapter_get_address(adapter),
7539 BT_IO_OPT_SOURCE_TYPE,
7540 btd_adapter_get_address_type(adapter),
7541 BT_IO_OPT_DEST_BDADDR, &dev->bdaddr,
7542 BT_IO_OPT_DEST_TYPE, dev->bdaddr_type,
7543 BT_IO_OPT_CID, ATT_CID,
7544 BT_IO_OPT_SEC_LEVEL, sec_level,
7549 DBusMessage *reply = btd_error_failed(
7550 dev->bonding->msg, gerr->message);
7552 g_dbus_send_message(dbus_conn, reply);
7553 bonding_request_cancel(dev->bonding);
7554 bonding_request_free(dev->bonding);
7557 error("ATT bt_io_connect(%s): %s", addr, gerr->message);
7562 /* Keep this, so we can cancel the connection */
7568 static struct browse_req *browse_request_new(struct btd_device *device,
7572 struct browse_req *req;
7577 req = g_new0(struct browse_req, 1);
7578 req->device = device;
7581 device->browse = req;
7586 req->msg = dbus_message_ref(msg);
7589 * Track the request owner to cancel it automatically if the owner
7592 req->listener_id = g_dbus_add_disconnect_watch(dbus_conn,
7593 dbus_message_get_sender(msg),
7594 browse_request_exit,
7600 static int device_browse_gatt(struct btd_device *device, DBusMessage *msg)
7602 struct btd_adapter *adapter = device->adapter;
7603 struct browse_req *req;
7605 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7608 req = browse_request_new(device, BROWSE_GATT, msg);
7612 if (device->client) {
7614 * If discovery has not yet completed, then wait for gatt-client
7617 if (!bt_gatt_client_is_ready(device->client))
7621 * Services have already been discovered, so signal this browse
7622 * request as resolved.
7624 device_svc_resolved(device, BROWSE_GATT, device->bdaddr_type,
7629 device->att_io = bt_io_connect(att_connect_cb,
7631 BT_IO_OPT_SOURCE_BDADDR,
7632 btd_adapter_get_address(adapter),
7633 BT_IO_OPT_SOURCE_TYPE,
7634 btd_adapter_get_address_type(adapter),
7635 BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
7636 BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
7637 BT_IO_OPT_CID, ATT_CID,
7638 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
7641 if (device->att_io == NULL) {
7642 browse_request_free(req);
7649 static uint16_t get_sdp_flags(struct btd_device *device)
7653 vid = btd_device_get_vendor(device);
7654 pid = btd_device_get_product(device);
7656 /* Sony DualShock 4 is not respecting negotiated L2CAP MTU. This might
7657 * results in SDP response being dropped by kernel. Workaround this by
7658 * forcing SDP code to use bigger MTU while connecting.
7660 if (vid == 0x054c && pid == 0x05c4)
7661 return SDP_LARGE_MTU;
7663 if (btd_adapter_ssp_enabled(device->adapter))
7666 /* if no EIR try matching Sony DualShock 4 with name and class */
7667 if (!strncmp(device->name, "Wireless Controller", MAX_NAME_LENGTH) &&
7668 device->class == 0x2508)
7669 return SDP_LARGE_MTU;
7674 static int device_browse_sdp(struct btd_device *device, DBusMessage *msg)
7676 struct btd_adapter *adapter = device->adapter;
7677 struct browse_req *req;
7681 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7684 req = browse_request_new(device, BROWSE_SDP, msg);
7688 sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
7690 req->sdp_flags = get_sdp_flags(device);
7692 err = bt_search_service(btd_adapter_get_address(adapter),
7693 &device->bdaddr, &uuid, browse_cb, req, NULL,
7696 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7697 device->browse = NULL;
7699 browse_request_free(req);
7706 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7707 void device_set_last_addr_type(struct btd_device *device, uint8_t type)
7712 //DBG("Last addr type %d", type);
7714 device->last_bdaddr_type = type;
7717 gboolean device_is_ipsp_connected(struct btd_device * device)
7719 return device->ipsp_connected;
7722 void device_set_ipsp_connected(struct btd_device *device, gboolean connected,
7723 const unsigned char *ifname)
7725 char *iface_name = NULL;
7727 if (device == NULL) {
7728 error("device is NULL");
7732 if (device->ipsp_connected == connected)
7735 device->ipsp_connected = connected;
7737 memset(device->if_name, 0, sizeof(device->if_name));
7738 memcpy(device->if_name, ifname, 16);
7739 iface_name = device->if_name;
7741 DBG("ipsp_connected %d", connected);
7742 DBG("ipsp_iface: %s is Up !", iface_name);
7744 g_dbus_emit_signal(dbus_conn, device->path,
7745 DEVICE_INTERFACE, "IpspStateChanged",
7746 DBUS_TYPE_BOOLEAN, &connected,
7747 DBUS_TYPE_STRING, &iface_name,
7750 void device_le_data_length_changed(struct btd_device *device, uint16_t max_tx_octets,
7751 uint16_t max_tx_time, uint16_t max_rx_octets, uint16_t max_rx_time)
7753 if (device == NULL) {
7754 error("device is NULL");
7758 device->max_tx_octets = max_tx_octets;
7759 device->max_tx_time = max_tx_time;
7760 device->max_rx_octets = max_rx_octets;
7761 device->max_rx_time = max_rx_time;
7763 DBG("data length changed values :max_tx_octets: %d max_tx_time: %d max_rx_octets: %d max_rx_time: %d",
7764 max_tx_octets, max_tx_time, max_rx_octets, max_rx_time);
7766 g_dbus_emit_signal(dbus_conn, device->path,
7767 DEVICE_INTERFACE, "LEDataLengthChanged",
7768 DBUS_TYPE_UINT16, &max_tx_octets,
7769 DBUS_TYPE_UINT16, &max_tx_time,
7770 DBUS_TYPE_UINT16, &max_rx_octets,
7771 DBUS_TYPE_UINT16, &max_rx_time,
7775 const bdaddr_t *device_get_rpa(struct btd_device *device)
7780 const uint8_t *device_get_irk_value(struct btd_device *device)
7782 return device->irk_val;
7785 bool device_get_rpa_exist(struct btd_device *device)
7787 return device->rpa ? true : false;
7790 void device_set_auth_addr_type(struct btd_device *device, uint8_t type)
7795 DBG("Auth addr type %d", type);
7797 device->auth_bdaddr_type = type;
7800 void device_get_tizen_addr(struct btd_device *device, uint8_t type,
7801 struct device_addr_type *addr)
7803 if (!device || !addr)
7806 if (type == BDADDR_BREDR) {
7807 bacpy(&addr->bdaddr, &device->bdaddr);
7808 addr->bdaddr_type = BDADDR_BREDR;
7813 bacpy(&addr->bdaddr, device->rpa);
7814 addr->bdaddr_type = BDADDR_LE_RANDOM;
7818 bacpy(&addr->bdaddr, &device->bdaddr);
7819 addr->bdaddr_type = device->bdaddr_type;
7823 int device_discover_services(struct btd_device *device)
7828 err = device_browse_sdp(device, NULL);
7830 err = device_browse_gatt(device, NULL);
7832 if (err == 0 && device->discov_timer) {
7833 g_source_remove(device->discov_timer);
7834 device->discov_timer = 0;
7840 struct btd_adapter *device_get_adapter(struct btd_device *device)
7845 return device->adapter;
7848 const bdaddr_t *device_get_address(struct btd_device *device)
7850 return &device->bdaddr;
7852 uint8_t device_get_le_address_type(struct btd_device *device)
7854 return device->bdaddr_type;
7857 const char *device_get_path(const struct btd_device *device)
7862 return device->path;
7865 gboolean device_is_temporary(struct btd_device *device)
7867 return device->temporary;
7870 void btd_device_set_temporary(struct btd_device *device, bool temporary)
7875 if (device->temporary == temporary)
7878 if (device_address_is_private(device))
7881 DBG("temporary %d", temporary);
7883 device->temporary = temporary;
7887 adapter_whitelist_remove(device->adapter, device);
7888 adapter_connect_list_remove(device->adapter, device);
7893 adapter_whitelist_add(device->adapter, device);
7895 store_device_info(device);
7897 /* attributes were not stored when resolved if device was temporary */
7898 if (device->bdaddr_type != BDADDR_BREDR &&
7899 device->le_state.svc_resolved &&
7900 g_slist_length(device->primaries) != 0)
7901 store_services(device);
7904 void btd_device_set_trusted(struct btd_device *device, gboolean trusted)
7909 if (device->trusted == trusted)
7912 DBG("trusted %d", trusted);
7914 device->trusted = trusted;
7916 store_device_info(device);
7918 g_dbus_emit_property_changed(dbus_conn, device->path,
7919 DEVICE_INTERFACE, "Trusted");
7922 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7923 void device_disconnect_blocked(struct btd_device *device, char *uuid)
7925 struct btd_service *service;
7928 if (!device || !uuid)
7931 l = find_service_with_uuid(device->services, uuid);
7936 if (btd_service_get_state(service) ==
7937 BTD_SERVICE_STATE_CONNECTED) {
7939 err = btd_service_disconnect(service);
7941 error("error: %s", strerror(-err));
7945 void btd_device_set_trusted_profiles(struct btd_device *device,
7946 uint32_t pbap, uint32_t map, uint32_t sap,
7947 uint32_t hfp_hs, uint32_t a2dp)
7952 DBG("TrustedProfiles Parameters: [PBAP %d] [MAP %d] [SAP %d] [HFP %d] [A2DP %d]",
7953 pbap, map, sap, hfp_hs, a2dp);
7955 if (device->trusted_profiles.pbap == pbap &&
7956 device->trusted_profiles.map == map &&
7957 device->trusted_profiles.sap == sap &&
7958 device->trusted_profiles.hfp_hs == hfp_hs &&
7959 device->trusted_profiles.a2dp == a2dp)
7962 /* Disconnect OBEX based profiles if connected */
7963 if (device->trusted_profiles.pbap != pbap) {
7964 device->trusted_profiles.pbap = pbap;
7965 if (pbap == SUPPORTED_BLOCKED)
7966 device_disconnect_blocked(device, OBEX_PSE_UUID);
7967 } else if (device->trusted_profiles.map != map) {
7968 device->trusted_profiles.map = map;
7969 if (map == SUPPORTED_BLOCKED)
7970 device_disconnect_blocked(device, OBEX_MAP_UUID);
7971 } else if (device->trusted_profiles.sap != sap) {
7972 device->trusted_profiles.sap = sap;
7973 if (sap == SUPPORTED_BLOCKED)
7974 device_disconnect_blocked(device, SAP_UUID);
7975 } else if (device->trusted_profiles.hfp_hs != hfp_hs) {
7976 device->trusted_profiles.hfp_hs = hfp_hs;
7977 } else if (device->trusted_profiles.a2dp != a2dp) {
7978 device->trusted_profiles.a2dp = a2dp;
7981 store_device_info(device);
7982 g_dbus_emit_property_changed(dbus_conn, device->path,
7983 DEVICE_INTERFACE, "TrustedProfiles");
7987 void device_set_bonded(struct btd_device *device, uint8_t bdaddr_type)
7994 if (bdaddr_type == BDADDR_BREDR)
7995 device->bredr_state.bonded = true;
7997 device->le_state.bonded = true;
7999 btd_device_set_temporary(device, false);
8002 void device_set_legacy(struct btd_device *device, bool legacy)
8007 DBG("legacy %d", legacy);
8009 if (device->legacy == legacy)
8012 device->legacy = legacy;
8014 g_dbus_emit_property_changed(dbus_conn, device->path,
8015 DEVICE_INTERFACE, "LegacyPairing");
8018 void device_store_svc_chng_ccc(struct btd_device *device, uint8_t bdaddr_type,
8021 char filename[PATH_MAX];
8022 char device_addr[18];
8028 ba2str(&device->bdaddr, device_addr);
8029 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
8030 btd_adapter_get_storage_dir(device->adapter),
8033 key_file = g_key_file_new();
8034 g_key_file_load_from_file(key_file, filename, 0, NULL);
8036 /* for bonded devices this is done on every connection so limit writes
8037 * to storage if no change needed
8039 if (bdaddr_type == BDADDR_BREDR) {
8040 old_value = g_key_file_get_integer(key_file, "ServiceChanged",
8041 "CCC_BR/EDR", NULL);
8042 if (old_value == value)
8045 g_key_file_set_integer(key_file, "ServiceChanged", "CCC_BR/EDR",
8048 old_value = g_key_file_get_integer(key_file, "ServiceChanged",
8050 if (old_value == value)
8053 g_key_file_set_integer(key_file, "ServiceChanged", "CCC_LE",
8057 create_file(filename, S_IRUSR | S_IWUSR);
8059 str = g_key_file_to_data(key_file, &length, NULL);
8060 g_file_set_contents(filename, str, length, NULL);
8064 g_key_file_free(key_file);
8066 void device_load_svc_chng_ccc(struct btd_device *device, uint16_t *ccc_le,
8067 uint16_t *ccc_bredr)
8069 char filename[PATH_MAX];
8070 char device_addr[18];
8073 ba2str(&device->bdaddr, device_addr);
8074 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
8075 btd_adapter_get_storage_dir(device->adapter),
8078 key_file = g_key_file_new();
8079 g_key_file_load_from_file(key_file, filename, 0, NULL);
8082 * If there is no "ServiceChanged" section we may be loading data from
8083 * old version which did not persist Service Changed CCC values. Let's
8084 * check if we are bonded and assume indications were enabled by peer
8085 * in such case - it should have done this anyway.
8087 if (!g_key_file_has_group(key_file, "ServiceChanged")) {
8089 *ccc_le = device->le_state.bonded ? 0x0002 : 0x0000;
8091 *ccc_bredr = device->bredr_state.bonded ?
8093 g_key_file_free(key_file);
8098 *ccc_le = g_key_file_get_integer(key_file, "ServiceChanged",
8102 *ccc_bredr = g_key_file_get_integer(key_file, "ServiceChanged",
8103 "CCC_BR/EDR", NULL);
8105 g_key_file_free(key_file);
8108 void device_set_rssi_with_delta(struct btd_device *device, int8_t rssi,
8109 int8_t delta_threshold)
8114 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8115 if (rssi == 0 || device->rssi == 0) {
8116 if (device->rssi == rssi)
8120 device->rssi = rssi;
8121 DBG("rssi %d", rssi);
8123 if (rssi == 0 || device->rssi == 0) {
8124 if (device->rssi == rssi)
8127 DBG("rssi %d", rssi);
8129 device->rssi = rssi;
8133 if (device->rssi > rssi)
8134 delta = device->rssi - rssi;
8136 delta = rssi - device->rssi;
8138 /* only report changes of delta_threshold dBm or more */
8139 if (delta < delta_threshold)
8142 DBG("rssi %d delta %d", rssi, delta);
8144 device->rssi = rssi;
8148 g_dbus_emit_property_changed(dbus_conn, device->path,
8149 DEVICE_INTERFACE, "RSSI");
8152 void device_set_rssi(struct btd_device *device, int8_t rssi)
8154 device_set_rssi_with_delta(device, rssi, RSSI_THRESHOLD);
8157 void device_set_tx_power(struct btd_device *device, int8_t tx_power)
8162 if (device->tx_power == tx_power)
8165 DBG("tx_power %d", tx_power);
8167 device->tx_power = tx_power;
8169 g_dbus_emit_property_changed(dbus_conn, device->path,
8170 DEVICE_INTERFACE, "TxPower");
8173 void device_set_flags(struct btd_device *device, uint8_t flags)
8178 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
8179 DBG("flags %d", flags);
8182 if (device->ad_flags[0] == flags)
8185 device->ad_flags[0] = flags;
8187 g_dbus_emit_property_changed(dbus_conn, device->path,
8188 DEVICE_INTERFACE, "AdvertisingFlags");
8191 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8192 void device_set_le_connectable(struct btd_device *device, uint8_t adv_type)
8197 if (device->le_connectable)
8200 if (adv_type == ADV_TYPE_IND || adv_type == ADV_TYPE_DIRECT_IND)
8201 device->le_connectable = true;
8205 bool device_is_connectable(struct btd_device *device)
8213 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8214 /* Check the ADV type. Some beacon device can be connectable regardless adv flags */
8215 return device->le_connectable;
8217 /* Check if either Limited or General discoverable are set */
8218 return (device->ad_flags[0] & 0x03);
8222 static gboolean start_discovery(gpointer user_data)
8224 struct btd_device *device = user_data;
8227 device_browse_sdp(device, NULL);
8229 device_browse_gatt(device, NULL);
8231 device->discov_timer = 0;
8236 void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type)
8238 struct bearer_state *state = get_state(dev, bdaddr_type);
8243 state->paired = true;
8245 /* If the other bearer state was already true we don't need to
8246 * send any property signals.
8248 if (dev->bredr_state.paired == dev->le_state.paired)
8251 if (!state->svc_resolved) {
8252 dev->pending_paired = true;
8256 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8257 if (dev->bonding == NULL)
8259 g_dbus_emit_property_changed(dbus_conn, dev->path,
8260 DEVICE_INTERFACE, "Paired");
8263 void device_set_unpaired(struct btd_device *dev, uint8_t bdaddr_type)
8265 struct bearer_state *state = get_state(dev, bdaddr_type);
8270 state->paired = false;
8273 * If the other bearer state is still true we don't need to
8274 * send any property signals or remove device.
8276 if (dev->bredr_state.paired != dev->le_state.paired) {
8277 /* TODO disconnect only unpaired bearer */
8278 if (state->connected)
8279 device_request_disconnect(dev, NULL);
8284 g_dbus_emit_property_changed(dbus_conn, dev->path,
8285 DEVICE_INTERFACE, "Paired");
8287 btd_device_set_temporary(dev, true);
8289 if (btd_device_is_connected(dev))
8290 device_request_disconnect(dev, NULL);
8292 btd_adapter_remove_device(dev->adapter, dev);
8295 static void device_auth_req_free(struct btd_device *device)
8297 struct authentication_req *authr = device->authr;
8303 agent_unref(authr->agent);
8305 g_free(authr->pincode);
8308 device->authr = NULL;
8311 bool device_is_retrying(struct btd_device *device)
8313 struct bonding_req *bonding = device->bonding;
8315 return bonding && bonding->retry_timer > 0;
8318 void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
8321 struct bonding_req *bonding = device->bonding;
8322 struct authentication_req *auth = device->authr;
8323 struct bearer_state *state = get_state(device, bdaddr_type);
8325 DBG("bonding %p status 0x%02x", bonding, status);
8327 if (auth && auth->agent)
8328 agent_cancel(auth->agent);
8331 device_cancel_authentication(device, TRUE);
8332 device_bonding_failed(device, status);
8333 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8334 device->legacy_pairing = false;
8338 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8339 device->legacy_pairing = false;
8341 device_auth_req_free(device);
8343 /* If we're already paired nothing more is needed */
8344 if (state->paired) {
8345 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8346 if (bdaddr_type == BDADDR_BREDR && state->svc_resolved) {
8347 DBG("Link key has been changed. Report it");
8349 g_dbus_emit_property_changed(dbus_conn,
8350 device->path, DEVICE_INTERFACE,
8353 DBG("Just overwrite Link key");
8354 } else if (bdaddr_type == BDADDR_LE_RANDOM ||
8355 bdaddr_type == BDADDR_LE_PUBLIC) {
8356 DBG("Long Term Key has been changed. Report it");
8357 g_dbus_emit_property_changed(dbus_conn, device->path,
8358 DEVICE_INTERFACE, "Paired");
8360 #endif /* TIZEN_FEATURE_BLUEZ_MODIFY */
8364 device_set_paired(device, bdaddr_type);
8366 /* If services are already resolved just reply to the pairing
8369 if (state->svc_resolved && bonding) {
8370 /* Attept to store services for this device failed because it
8371 * was not paired. Now that we're paired retry. */
8372 store_gatt_db(device);
8374 g_dbus_send_reply(dbus_conn, bonding->msg, DBUS_TYPE_INVALID);
8375 bonding_request_free(bonding);
8379 /* If we were initiators start service discovery immediately.
8380 * However if the other end was the initator wait a few seconds
8381 * before SDP. This is due to potential IOP issues if the other
8382 * end starts doing SDP at the same time as us */
8384 DBG("Proceeding with service discovery");
8385 /* If we are initiators remove any discovery timer and just
8386 * start discovering services directly */
8387 if (device->discov_timer) {
8388 g_source_remove(device->discov_timer);
8389 device->discov_timer = 0;
8392 if (bdaddr_type == BDADDR_BREDR)
8393 device_browse_sdp(device, bonding->msg);
8395 device_browse_gatt(device, bonding->msg);
8397 bonding_request_free(bonding);
8398 } else if (!state->svc_resolved) {
8399 if (!device->browse && !device->discov_timer &&
8400 main_opts.reverse_discovery) {
8401 /* If we are not initiators and there is no currently
8402 * active discovery or discovery timer, set discovery
8404 DBG("setting timer for reverse service discovery");
8405 device->discov_timer = g_timeout_add_seconds(
8413 static gboolean svc_idle_cb(gpointer user_data)
8415 struct svc_callback *cb = user_data;
8416 struct btd_device *dev = cb->dev;
8418 dev->svc_callbacks = g_slist_remove(dev->svc_callbacks, cb);
8420 cb->func(cb->dev, 0, cb->user_data);
8427 unsigned int device_wait_for_svc_complete(struct btd_device *dev,
8428 device_svc_cb_t func,
8431 /* This API is only used for BR/EDR (for now) */
8432 struct bearer_state *state = &dev->bredr_state;
8433 static unsigned int id = 0;
8434 struct svc_callback *cb;
8436 cb = g_new0(struct svc_callback, 1);
8438 cb->user_data = user_data;
8442 dev->svc_callbacks = g_slist_prepend(dev->svc_callbacks, cb);
8444 if (state->svc_resolved || !main_opts.reverse_discovery)
8445 cb->idle_id = g_idle_add(svc_idle_cb, cb);
8446 else if (dev->discov_timer > 0) {
8447 g_source_remove(dev->discov_timer);
8448 dev->discov_timer = g_idle_add(start_discovery, dev);
8450 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8451 else if (!dev->browse) {
8452 DBG("Service is not going on. Start discovery");
8453 dev->discov_timer = g_idle_add(start_discovery, dev);
8455 DBG("Wait for service discovery");
8461 bool device_remove_svc_complete_callback(struct btd_device *dev,
8466 for (l = dev->svc_callbacks; l != NULL; l = g_slist_next(l)) {
8467 struct svc_callback *cb = l->data;
8472 if (cb->idle_id > 0)
8473 g_source_remove(cb->idle_id);
8475 dev->svc_callbacks = g_slist_remove(dev->svc_callbacks, cb);
8484 gboolean device_is_bonding(struct btd_device *device, const char *sender)
8486 struct bonding_req *bonding = device->bonding;
8488 if (!device->bonding)
8494 return g_str_equal(sender, dbus_message_get_sender(bonding->msg));
8497 static gboolean device_bonding_retry(gpointer data)
8499 struct btd_device *device = data;
8500 struct btd_adapter *adapter = device_get_adapter(device);
8501 struct bonding_req *bonding = device->bonding;
8508 DBG("retrying bonding");
8509 bonding->retry_timer = 0;
8511 /* Restart the bonding timer to the begining of the pairing. If not
8512 * pincode request/reply occurs during this retry,
8513 * device_bonding_last_duration() will return a consistent value from
8515 device_bonding_restart_timer(device);
8518 io_cap = agent_get_io_capability(bonding->agent);
8520 io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
8522 err = adapter_bonding_attempt(adapter, &device->bdaddr,
8523 device->bdaddr_type, io_cap);
8525 device_bonding_complete(device, bonding->bdaddr_type,
8531 int device_bonding_attempt_retry(struct btd_device *device)
8533 struct bonding_req *bonding = device->bonding;
8535 /* Ignore other failure events while retrying */
8536 if (device_is_retrying(device))
8542 /* Mark the end of a bonding attempt to compute the delta for the
8544 bonding_request_stop_timer(bonding);
8546 if (btd_adapter_pin_cb_iter_end(bonding->cb_iter))
8549 DBG("scheduling retry");
8550 bonding->retry_timer = g_timeout_add(3000,
8551 device_bonding_retry, device);
8555 void device_bonding_failed(struct btd_device *device, uint8_t status)
8557 struct bonding_req *bonding = device->bonding;
8560 DBG("status %u", status);
8563 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8564 if (device->legacy_pairing) {
8565 DBG("Emit LegacyPaired");
8566 g_dbus_emit_property_changed(dbus_conn, device->path,
8567 DEVICE_INTERFACE, "LegacyPaired");
8572 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8573 btd_device_set_temporary(device, TRUE);
8577 device_cancel_authentication(device, FALSE);
8579 reply = new_authentication_return(bonding->msg, status);
8580 g_dbus_send_message(dbus_conn, reply);
8582 bonding_request_free(bonding);
8585 struct btd_adapter_pin_cb_iter *device_bonding_iter(struct btd_device *device)
8587 if (device->bonding == NULL)
8590 return device->bonding->cb_iter;
8593 static void pincode_cb(struct agent *agent, DBusError *err, const char *pin,
8596 struct authentication_req *auth = data;
8597 struct btd_device *device = auth->device;
8599 /* No need to reply anything if the authentication already failed */
8600 if (auth->agent == NULL)
8603 btd_adapter_pincode_reply(device->adapter, &device->bdaddr,
8604 pin, pin ? strlen(pin) : 0);
8606 agent_unref(device->authr->agent);
8607 device->authr->agent = NULL;
8610 static void confirm_cb(struct agent *agent, DBusError *err, void *data)
8612 struct authentication_req *auth = data;
8613 struct btd_device *device = auth->device;
8615 /* No need to reply anything if the authentication already failed */
8616 if (auth->agent == NULL)
8619 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8620 btd_adapter_confirm_reply(device->adapter, &device->bdaddr,
8622 err ? FALSE : TRUE);
8623 device_set_auth_addr_type(device, BDADDR_BREDR);
8625 btd_adapter_confirm_reply(device->adapter, &device->bdaddr,
8627 err ? FALSE : TRUE);
8630 agent_unref(device->authr->agent);
8631 device->authr->agent = NULL;
8634 static void passkey_cb(struct agent *agent, DBusError *err,
8635 uint32_t passkey, void *data)
8637 struct authentication_req *auth = data;
8638 struct btd_device *device = auth->device;
8640 /* No need to reply anything if the authentication already failed */
8641 if (auth->agent == NULL)
8645 passkey = INVALID_PASSKEY;
8647 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8648 btd_adapter_passkey_reply(device->adapter, &device->bdaddr,
8649 auth->addr_type, passkey);
8650 device_set_auth_addr_type(device, BDADDR_BREDR);
8652 btd_adapter_passkey_reply(device->adapter, &device->bdaddr,
8653 auth->addr_type, passkey);
8656 agent_unref(device->authr->agent);
8657 device->authr->agent = NULL;
8660 static void display_pincode_cb(struct agent *agent, DBusError *err, void *data)
8662 struct authentication_req *auth = data;
8663 struct btd_device *device = auth->device;
8665 pincode_cb(agent, err, auth->pincode, auth);
8667 g_free(device->authr->pincode);
8668 device->authr->pincode = NULL;
8671 static struct authentication_req *new_auth(struct btd_device *device,
8676 struct authentication_req *auth;
8677 struct agent *agent;
8680 ba2str(&device->bdaddr, addr);
8681 DBG("Requesting agent authentication for %s", addr);
8683 if (device->authr) {
8684 error("Authentication already requested for %s", addr);
8688 if (device->bonding && device->bonding->agent)
8689 agent = agent_ref(device->bonding->agent);
8691 agent = agent_get(NULL);
8694 error("No agent available for request type %d", type);
8698 auth = g_new0(struct authentication_req, 1);
8699 auth->agent = agent;
8700 auth->device = device;
8702 auth->addr_type = addr_type;
8703 auth->secure = secure;
8704 device->authr = auth;
8709 int device_request_pincode(struct btd_device *device, gboolean secure)
8711 struct authentication_req *auth;
8714 auth = new_auth(device, BDADDR_BREDR, AUTH_TYPE_PINCODE, secure);
8718 err = agent_request_pincode(auth->agent, device, pincode_cb, secure,
8721 error("Failed requesting authentication");
8722 device_auth_req_free(device);
8728 int device_request_passkey(struct btd_device *device, uint8_t type)
8730 struct authentication_req *auth;
8733 auth = new_auth(device, type, AUTH_TYPE_PASSKEY, FALSE);
8737 err = agent_request_passkey(auth->agent, device, passkey_cb, auth,
8740 error("Failed requesting authentication");
8741 device_auth_req_free(device);
8747 int device_confirm_passkey(struct btd_device *device, uint8_t type,
8748 int32_t passkey, uint8_t confirm_hint)
8750 struct authentication_req *auth;
8753 auth = new_auth(device, type, AUTH_TYPE_CONFIRM, FALSE);
8757 auth->passkey = passkey;
8759 #ifndef TIZEN_FEATURE_BLUEZ_CONFIRM_ONLY
8761 err = agent_request_authorization(auth->agent, device,
8762 confirm_cb, auth, NULL);
8765 err = agent_request_confirmation(auth->agent, device, passkey,
8766 confirm_cb, auth, NULL);
8769 error("Failed requesting authentication");
8770 device_auth_req_free(device);
8776 int device_notify_passkey(struct btd_device *device, uint8_t type,
8777 uint32_t passkey, uint8_t entered)
8779 struct authentication_req *auth;
8782 if (device->authr) {
8783 auth = device->authr;
8784 if (auth->type != AUTH_TYPE_NOTIFY_PASSKEY)
8787 auth = new_auth(device, type, AUTH_TYPE_NOTIFY_PASSKEY, FALSE);
8792 err = agent_display_passkey(auth->agent, device, passkey, entered);
8794 error("Failed requesting authentication");
8795 device_auth_req_free(device);
8801 int device_notify_pincode(struct btd_device *device, gboolean secure,
8802 const char *pincode)
8804 struct authentication_req *auth;
8807 auth = new_auth(device, BDADDR_BREDR, AUTH_TYPE_NOTIFY_PINCODE, secure);
8811 auth->pincode = g_strdup(pincode);
8813 err = agent_display_pincode(auth->agent, device, pincode,
8814 display_pincode_cb, auth, NULL);
8816 error("Failed requesting authentication");
8817 device_auth_req_free(device);
8823 static void cancel_authentication(struct authentication_req *auth)
8825 struct agent *agent;
8828 if (!auth || !auth->agent)
8831 agent = auth->agent;
8834 dbus_error_init(&err);
8835 dbus_set_error_const(&err, ERROR_INTERFACE ".Canceled", NULL);
8837 switch (auth->type) {
8838 case AUTH_TYPE_PINCODE:
8839 pincode_cb(agent, &err, NULL, auth);
8841 case AUTH_TYPE_CONFIRM:
8842 confirm_cb(agent, &err, auth);
8844 case AUTH_TYPE_PASSKEY:
8845 passkey_cb(agent, &err, 0, auth);
8847 case AUTH_TYPE_NOTIFY_PASSKEY:
8848 /* User Notify doesn't require any reply */
8850 case AUTH_TYPE_NOTIFY_PINCODE:
8851 pincode_cb(agent, &err, NULL, auth);
8855 dbus_error_free(&err);
8858 void device_cancel_authentication(struct btd_device *device, gboolean aborted)
8860 struct authentication_req *auth = device->authr;
8866 ba2str(&device->bdaddr, addr);
8867 DBG("Canceling authentication request for %s", addr);
8870 agent_cancel(auth->agent);
8873 cancel_authentication(auth);
8875 device_auth_req_free(device);
8877 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8878 device_set_auth_addr_type(device, BDADDR_BREDR);
8882 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8883 gboolean device_is_authenticating(struct btd_device *dev, uint8_t bdaddr_type)
8885 return (dev->auth_bdaddr_type == bdaddr_type && dev->authr != NULL);
8888 gboolean device_is_authenticating(struct btd_device *device)
8890 return (device->authr != NULL);
8894 struct gatt_primary *btd_device_get_primary(struct btd_device *device,
8899 match = g_slist_find_custom(device->primaries, uuid, bt_uuid_strcmp);
8906 GSList *btd_device_get_primaries(struct btd_device *device)
8908 return device->primaries;
8911 struct gatt_db *btd_device_get_gatt_db(struct btd_device *device)
8919 struct bt_gatt_client *btd_device_get_gatt_client(struct btd_device *device)
8924 return device->client;
8927 void *btd_device_get_attrib(struct btd_device *device)
8932 return device->attrib;
8935 struct bt_gatt_server *btd_device_get_gatt_server(struct btd_device *device)
8940 return device->server;
8943 void btd_device_gatt_set_service_changed(struct btd_device *device,
8944 uint16_t start, uint16_t end)
8947 * TODO: Remove this function and handle service changed via
8952 void btd_device_add_uuid(struct btd_device *device, const char *uuid)
8957 if (g_slist_find_custom(device->uuids, uuid, bt_uuid_strcmp))
8960 new_uuid = g_strdup(uuid);
8961 uuid_list = g_slist_append(NULL, new_uuid);
8963 device_probe_profiles(device, uuid_list);
8966 g_slist_free(uuid_list);
8968 store_device_info(device);
8970 g_dbus_emit_property_changed(dbus_conn, device->path,
8971 DEVICE_INTERFACE, "UUIDs");
8974 static sdp_list_t *read_device_records(struct btd_device *device)
8976 char local[18], peer[18];
8977 char filename[PATH_MAX];
8979 char **keys, **handle;
8981 sdp_list_t *recs = NULL;
8984 ba2str(btd_adapter_get_address(device->adapter), local);
8985 ba2str(&device->bdaddr, peer);
8987 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8989 ba2str(device->rpa, peer);
8992 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
8994 key_file = g_key_file_new();
8995 g_key_file_load_from_file(key_file, filename, 0, NULL);
8996 keys = g_key_file_get_keys(key_file, "ServiceRecords", NULL, NULL);
8998 for (handle = keys; handle && *handle; handle++) {
8999 str = g_key_file_get_string(key_file, "ServiceRecords",
9004 rec = record_from_string(str);
9005 recs = sdp_list_append(recs, rec);
9010 g_key_file_free(key_file);
9015 void btd_device_set_record(struct btd_device *device, const char *uuid,
9018 /* This API is only used for BR/EDR */
9019 struct bearer_state *state = &device->bredr_state;
9020 struct browse_req *req;
9021 sdp_list_t *recs = NULL;
9027 req = browse_request_new(device, BROWSE_SDP, NULL);
9031 rec = record_from_string(record);
9032 recs = sdp_list_append(recs, rec);
9033 update_bredr_services(req, recs);
9034 sdp_list_free(recs, NULL);
9036 device->svc_refreshed = true;
9037 state->svc_resolved = true;
9039 device_probe_profiles(device, req->profiles_added);
9041 /* Propagate services changes */
9042 g_dbus_emit_property_changed(dbus_conn, req->device->path,
9043 DEVICE_INTERFACE, "UUIDs");
9045 device_svc_resolved(device, BROWSE_SDP, device->bdaddr_type, 0);
9048 const sdp_record_t *btd_device_get_record(struct btd_device *device,
9051 /* Load records from storage if there is nothing in cache */
9052 if (!device->tmp_records) {
9053 device->tmp_records = read_device_records(device);
9054 if (!device->tmp_records)
9058 return find_record_in_list(device->tmp_records, uuid);
9061 struct btd_device *btd_device_ref(struct btd_device *device)
9063 __sync_fetch_and_add(&device->ref_count, 1);
9068 void btd_device_unref(struct btd_device *device)
9070 if (__sync_sub_and_fetch(&device->ref_count, 1))
9073 if (!device->path) {
9074 error("freeing device without an object path");
9078 DBG("Freeing device %s", device->path);
9080 g_dbus_unregister_interface(dbus_conn, device->path, DEVICE_INTERFACE);
9083 int device_get_appearance(struct btd_device *device, uint16_t *value)
9085 if (device->appearance == 0)
9089 *value = device->appearance;
9094 void device_set_appearance(struct btd_device *device, uint16_t value)
9096 const char *icon = gap_appearance_to_icon(value);
9098 if (device->appearance == value)
9101 g_dbus_emit_property_changed(dbus_conn, device->path,
9102 DEVICE_INTERFACE, "Appearance");
9105 g_dbus_emit_property_changed(dbus_conn, device->path,
9106 DEVICE_INTERFACE, "Icon");
9108 device->appearance = value;
9109 store_device_info(device);
9112 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9113 int device_get_rpa_res_char_value(struct btd_device *device)
9115 return device->rpa_res_support;
9118 /* Store the RPA Resolution Characteristic Value of remote device.
9119 * This value would be checked before start directed advertising using RPA.
9121 void device_set_rpa_res_char_value(struct btd_device *device, uint8_t value)
9123 if (device->rpa_res_support == value)
9126 device->rpa_res_support = value;
9127 store_device_info(device);
9130 void device_set_manufacturer_info(struct btd_device *device, struct eir_data *eir)
9135 if (eir->manufacturer_data_len == 0)
9138 device->manufacturer_data = g_memdup(eir->manufacturer_data,
9139 eir->manufacturer_data_len);
9140 device->manufacturer_data_len = eir->manufacturer_data_len;
9142 store_device_info(device);
9144 g_dbus_emit_property_changed(dbus_conn, device->path,
9145 DEVICE_INTERFACE, "LegacyManufacturerDataLen");
9147 g_dbus_emit_property_changed(dbus_conn, device->path,
9148 DEVICE_INTERFACE, "LegacyManufacturerData");
9152 void device_set_adv_report_info(struct btd_device *device, void *data, uint8_t data_len,
9153 uint8_t adv_type, int8_t rssi)
9159 const char *paddr = peer_addr;
9160 dbus_int32_t rssi_val = rssi;
9161 int adv_len = data_len;
9164 ba2str(&device->bdaddr, peer_addr);
9166 /* Replace address type for paired RPA device since IDA passed from controller */
9168 ba2str(device->rpa, peer_addr);
9169 addr_type = BDADDR_LE_RANDOM;
9171 addr_type = device->bdaddr_type;
9173 g_dbus_emit_signal(dbus_conn, device->path,
9174 DEVICE_INTERFACE, "AdvReport",
9175 DBUS_TYPE_STRING, &paddr,
9176 DBUS_TYPE_BYTE, &addr_type,
9177 DBUS_TYPE_BYTE, &adv_type,
9178 DBUS_TYPE_INT32, &rssi_val,
9179 DBUS_TYPE_INT32, &adv_len,
9180 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_len,
9184 void device_set_payload_timeout(struct btd_device *device,
9185 uint16_t payload_timeout)
9189 if (device->auth_payload_timeout == payload_timeout)
9192 DBG("Payload timeout %d", payload_timeout);
9194 device->auth_payload_timeout = payload_timeout;
9195 g_dbus_emit_property_changed(dbus_conn, device->path,
9196 DEVICE_INTERFACE, "PayloadTimeout");
9199 void device_set_disconnect_reason(struct btd_device *device, uint8_t reason)
9201 device->disc_reason = reason;
9204 void btd_device_disconnect(struct btd_device *device)
9207 struct btd_service *service;
9208 btd_service_state_t state;
9210 ba2str(&device->bdaddr, dst);
9213 if (device->bredr_state.connected == false)
9216 service = btd_device_get_service(device, HFP_HS_UUID);
9220 state = btd_service_get_state(service);
9221 DBG("Connected State : %d", state);
9223 if (state == BTD_SERVICE_STATE_DISCONNECTED) {
9224 btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
9233 void btd_device_set_pnpid(struct btd_device *device, uint16_t source,
9234 uint16_t vendor, uint16_t product, uint16_t version)
9236 if (device->vendor_src == source && device->version == version &&
9237 device->vendor == vendor && device->product == product)
9240 device->vendor_src = source;
9241 device->vendor = vendor;
9242 device->product = product;
9243 device->version = version;
9245 free(device->modalias);
9246 device->modalias = bt_modalias(source, vendor, product, version);
9248 g_dbus_emit_property_changed(dbus_conn, device->path,
9249 DEVICE_INTERFACE, "Modalias");
9251 store_device_info(device);
9254 static void service_state_changed(struct btd_service *service,
9255 btd_service_state_t old_state,
9256 btd_service_state_t new_state,
9259 struct btd_profile *profile = btd_service_get_profile(service);
9260 struct btd_device *device = btd_service_get_device(service);
9261 int err = btd_service_get_error(service);
9263 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9265 if (old_state == BTD_SERVICE_STATE_UNAVAILABLE ||
9266 new_state == BTD_SERVICE_STATE_UNAVAILABLE)
9267 DBG("Skip status updating ([%d] -> [%d])", old_state, new_state);
9269 g_dbus_emit_signal(dbus_conn, device->path,
9270 DEVICE_INTERFACE, "ProfileStateChanged",
9271 DBUS_TYPE_STRING, &profile->remote_uuid,
9272 DBUS_TYPE_INT32, &new_state,
9276 if (new_state == BTD_SERVICE_STATE_CONNECTING ||
9277 new_state == BTD_SERVICE_STATE_DISCONNECTING ||
9278 new_state == BTD_SERVICE_STATE_UNAVAILABLE)
9280 if (new_state == BTD_SERVICE_STATE_CONNECTING ||
9281 new_state == BTD_SERVICE_STATE_DISCONNECTING)
9285 if (old_state == BTD_SERVICE_STATE_CONNECTING)
9286 device_profile_connected(device, profile, err);
9287 else if (old_state == BTD_SERVICE_STATE_DISCONNECTING)
9288 device_profile_disconnected(device, profile, err);
9291 struct btd_service *btd_device_get_service(struct btd_device *dev,
9292 const char *remote_uuid)
9296 for (l = dev->services; l != NULL; l = g_slist_next(l)) {
9297 struct btd_service *service = l->data;
9298 struct btd_profile *p = btd_service_get_profile(service);
9300 if (g_str_equal(p->remote_uuid, remote_uuid))
9303 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
9304 if (g_str_equal(HID_UUID, remote_uuid)) {
9305 if (strcmp(p->name, "hid-device") == 0)
9314 void btd_device_init(void)
9316 dbus_conn = btd_get_dbus_connection();
9317 service_state_cb_id = btd_service_add_state_cb(
9318 service_state_changed, NULL);
9321 void btd_device_cleanup(void)
9323 btd_service_remove_state_cb(service_state_cb_id);
9326 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9327 void btd_device_set_legacy_pairing(struct btd_device *dev, bool legacy_pairing)
9329 dev->legacy_pairing = legacy_pairing;
9332 void btd_device_set_svc_changed_indication(struct btd_device *dev, bool value)
9334 bt_att_set_svc_changed_indication_registered(dev->att, value);
9335 store_device_info(dev);
9338 bool btd_device_get_svc_changed_indication(struct btd_device *dev)
9340 return bt_att_get_svc_changed_indication_registered(dev->att);