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 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
389 #define BT_L2CAP_LE_INTERFACE_NAME "org.bluez.l2cap_le"
390 #define BTD_L2CAP_LE_PSM_MAX 0xFFFF
394 BT_L2CAP_LE_CLIENT_ROLE = 0x00,
395 BT_L2CAP_LE_SERVER_ROLE,
396 } bt_l2cap_le_role_e;
398 struct l2cap_le_conn_info {
399 struct l2cap_le_profile_info *profile_info;
403 const char *dev_path;
409 struct l2cap_le_profile_info {
413 bt_l2cap_le_role_e role;
415 BtIOSecLevel sec_level;
418 struct l2cap_le_conn_info *server;
422 GSList *l2cap_le_socket_list = NULL;
426 static int device_browse_gatt(struct btd_device *device, DBusMessage *msg);
427 static int device_browse_sdp(struct btd_device *device, DBusMessage *msg);
429 static struct bearer_state *get_state(struct btd_device *dev,
432 if (bdaddr_type == BDADDR_BREDR)
433 return &dev->bredr_state;
435 return &dev->le_state;
438 static GSList *find_service_with_profile(GSList *list, struct btd_profile *p)
442 for (l = list; l != NULL; l = g_slist_next(l)) {
443 struct btd_service *service = l->data;
445 if (btd_service_get_profile(service) == p)
452 static GSList *find_service_with_state(GSList *list,
453 btd_service_state_t state)
457 for (l = list; l != NULL; l = g_slist_next(l)) {
458 struct btd_service *service = l->data;
460 if (btd_service_get_state(service) == state)
467 static GSList *find_service_with_uuid(GSList *list, char *uuid)
471 for (l = list; l != NULL; l = g_slist_next(l)) {
472 struct btd_service *service = l->data;
473 struct btd_profile *profile = btd_service_get_profile(service);
475 if (bt_uuid_strcmp(profile->remote_uuid, uuid) == 0)
482 static void update_technologies(GKeyFile *file, struct btd_device *dev)
488 list[len++] = "BR/EDR";
493 if (dev->bdaddr_type == BDADDR_LE_PUBLIC)
498 g_key_file_set_string(file, "General", "AddressType", type);
503 g_key_file_set_string_list(file, "General", "SupportedTechnologies",
507 static void store_csrk(struct csrk_info *csrk, GKeyFile *key_file,
513 for (i = 0; i < 16; i++)
514 sprintf(key + (i * 2), "%2.2X", csrk->key[i]);
516 g_key_file_set_string(key_file, group, "Key", key);
517 g_key_file_set_integer(key_file, group, "Counter", csrk->counter);
520 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
521 static char *manufacturer_data2str(char *data, int size)
523 char str[DEV_MAX_MANUFACTURER_DATA_LEN * 3 + 1];
528 for(i = 0; i < size; i++) {
529 snprintf(tmp, sizeof(tmp), "%d ", data[i]);
530 g_strlcat(str, tmp, sizeof(str));
533 return g_strdup(str);
536 static void load_manufacturer_data_2digit(char *data, int len, char *buf)
541 split = g_strsplit(data, " ", 0);
543 for (i = 0; i < len; i++) {
544 if (split[i] == NULL)
547 buf[i] = (char)g_ascii_strtoull(split[i], NULL, 10);
556 static gboolean store_device_info_cb(gpointer user_data)
558 struct btd_device *device = user_data;
560 char filename[PATH_MAX];
561 char device_addr[18];
566 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
567 gboolean svc_change_regd = false;
570 device->store_id = 0;
572 ba2str(&device->bdaddr, device_addr);
574 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
576 ba2str(device->rpa, device_addr);
578 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
579 btd_adapter_get_storage_dir(device->adapter),
582 key_file = g_key_file_new();
583 g_key_file_load_from_file(key_file, filename, 0, NULL);
585 g_key_file_set_string(key_file, "General", "Name", device->name);
587 if (device->alias != NULL)
588 g_key_file_set_string(key_file, "General", "Alias",
591 g_key_file_remove_key(key_file, "General", "Alias", NULL);
594 sprintf(class, "0x%6.6x", device->class);
595 g_key_file_set_string(key_file, "General", "Class", class);
597 g_key_file_remove_key(key_file, "General", "Class", NULL);
600 if (device->appearance) {
601 sprintf(class, "0x%4.4x", device->appearance);
602 g_key_file_set_string(key_file, "General", "Appearance", class);
604 g_key_file_remove_key(key_file, "General", "Appearance", NULL);
607 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
608 if (device->rpa_res_support) {
609 g_key_file_set_integer(key_file, "General", "RPAResSupport",
610 device->rpa_res_support);
612 g_key_file_remove_key(key_file, "General", "RPAResSupport", NULL);
616 update_technologies(key_file, device);
618 g_key_file_set_boolean(key_file, "General", "Trusted",
620 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
621 struct trusted_profile_t trust_profile = device->trusted_profiles;
622 int trusted_profiles = (trust_profile.pbap << PBAP_SHIFT_OFFSET) |
623 (trust_profile.map << MAP_SHIFT_OFFSET) |
624 (trust_profile.sap << SAP_SHIFT_OFFSET) |
625 (trust_profile.hfp_hs << HFP_HS_SHIFT_OFFSET) |
626 (trust_profile.a2dp << A2DP_SHIFT_OFFSET);
627 DBG("Storing TrustedProfiles %d", trusted_profiles);
628 g_key_file_set_integer(key_file, "General", "TrustedProfiles",
631 g_key_file_set_boolean(key_file, "General", "Blocked",
638 uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
639 for (i = 0, l = device->uuids; l; l = g_slist_next(l), i++)
641 g_key_file_set_string_list(key_file, "General", "Services",
642 (const char **)uuids, i);
644 g_key_file_remove_key(key_file, "General", "Services", NULL);
647 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
648 if (device->le_adv_data.flags) {
649 g_key_file_set_integer(key_file, "General", "Flags",
650 device->le_adv_data.flags);
652 g_key_file_remove_key(key_file, "General", "Flags", NULL);
655 if (device->manufacturer_data) {
656 str = manufacturer_data2str(device->manufacturer_data,
657 device->manufacturer_data_len);
658 g_key_file_set_string(key_file, "General",
659 "LegacyManufacturerData",
662 g_key_file_set_integer(key_file, "General",
663 "LegacyManufacturerDataLen",
664 device->manufacturer_data_len);
666 g_key_file_remove_key(key_file, "General",
667 "LegacyManufacturerData", NULL);
668 g_key_file_remove_key(key_file, "General",
669 "LegacyManufacturerDataLen", NULL);
675 ba2str(&device->bdaddr, irk_addr);
676 g_key_file_set_string(key_file, "General", "IdentityAddress",
679 g_key_file_remove_key(key_file, "General", "IdentityAddress",
684 if (device->vendor_src) {
685 g_key_file_set_integer(key_file, "DeviceID", "Source",
687 g_key_file_set_integer(key_file, "DeviceID", "Vendor",
689 g_key_file_set_integer(key_file, "DeviceID", "Product",
691 g_key_file_set_integer(key_file, "DeviceID", "Version",
694 g_key_file_remove_group(key_file, "DeviceID", NULL);
697 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
698 svc_change_regd = bt_att_get_svc_changed_indication_registered(device->att);
699 g_key_file_set_boolean(key_file, "Att", "SvcChangeRegd",
703 if (device->local_csrk)
704 store_csrk(device->local_csrk, key_file, "LocalSignatureKey");
706 if (device->remote_csrk)
707 store_csrk(device->remote_csrk, key_file, "RemoteSignatureKey");
709 create_file(filename, S_IRUSR | S_IWUSR);
711 str = g_key_file_to_data(key_file, &length, NULL);
712 g_file_set_contents(filename, str, length, NULL);
715 g_key_file_free(key_file);
721 static bool device_address_is_private(struct btd_device *dev)
723 if (dev->bdaddr_type != BDADDR_LE_RANDOM)
726 switch (dev->bdaddr.b[5] >> 6) {
727 case 0x00: /* Private non-resolvable */
728 case 0x01: /* Private resolvable */
735 static void store_device_info(struct btd_device *device)
737 if (device->temporary || device->store_id > 0)
740 if (device_address_is_private(device)) {
741 DBG("Can't store info for private addressed device %s",
746 device->store_id = g_idle_add(store_device_info_cb, device);
749 void device_store_cached_name(struct btd_device *dev, const char *name)
751 char filename[PATH_MAX];
757 if (device_address_is_private(dev)) {
758 DBG("Can't store name for private addressed device %s",
763 ba2str(&dev->bdaddr, d_addr);
765 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
767 ba2str(dev->rpa, d_addr);
770 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
771 btd_adapter_get_storage_dir(dev->adapter), d_addr);
772 create_file(filename, S_IRUSR | S_IWUSR);
774 key_file = g_key_file_new();
775 g_key_file_load_from_file(key_file, filename, 0, NULL);
776 g_key_file_set_string(key_file, "General", "Name", name);
778 data = g_key_file_to_data(key_file, &length, NULL);
779 g_file_set_contents(filename, data, length, NULL);
782 g_key_file_free(key_file);
785 static void browse_request_free(struct browse_req *req)
787 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
790 struct btd_device *device = req->device;
792 if (device->browse == req)
793 device->browse = NULL;
795 if (req->listener_id)
796 g_dbus_remove_watch(dbus_conn, req->listener_id);
798 dbus_message_unref(req->msg);
799 g_slist_free_full(req->profiles_added, g_free);
801 sdp_list_free(req->records, (sdp_free_func_t) sdp_record_free);
806 static bool gatt_cache_is_enabled(struct btd_device *device)
808 switch (main_opts.gatt_cache) {
809 case BT_GATT_CACHE_YES:
810 return device_is_paired(device, device->bdaddr_type);
811 case BT_GATT_CACHE_NO:
813 case BT_GATT_CACHE_ALWAYS:
819 static void gatt_cache_cleanup(struct btd_device *device)
821 if (gatt_cache_is_enabled(device))
824 gatt_db_clear(device->db);
827 static void gatt_client_cleanup(struct btd_device *device)
832 gatt_cache_cleanup(device);
833 bt_gatt_client_set_service_changed(device->client, NULL, NULL, NULL);
835 if (device->gatt_ready_id > 0) {
836 bt_gatt_client_ready_unregister(device->client,
837 device->gatt_ready_id);
838 device->gatt_ready_id = 0;
841 bt_gatt_client_unref(device->client);
842 device->client = NULL;
845 static void gatt_server_cleanup(struct btd_device *device)
850 btd_gatt_database_att_disconnected(
851 btd_adapter_get_database(device->adapter), device);
853 bt_gatt_server_unref(device->server);
854 device->server = NULL;
857 static void attio_cleanup(struct btd_device *device)
859 if (device->att_disconn_id)
860 bt_att_unregister_disconnect(device->att,
861 device->att_disconn_id);
863 if (device->att_io) {
864 g_io_channel_shutdown(device->att_io, FALSE, NULL);
865 g_io_channel_unref(device->att_io);
866 device->att_io = NULL;
869 gatt_client_cleanup(device);
870 gatt_server_cleanup(device);
873 bt_att_unref(device->att);
877 if (device->attrib) {
878 GAttrib *attrib = device->attrib;
880 device->attrib = NULL;
881 g_attrib_cancel_all(attrib);
882 g_attrib_unref(attrib);
886 static void browse_request_cancel(struct browse_req *req)
888 struct btd_device *device = req->device;
889 struct btd_adapter *adapter = device->adapter;
893 bt_cancel_discovery(btd_adapter_get_address(adapter), &device->bdaddr);
895 attio_cleanup(device);
897 browse_request_free(req);
900 static void svc_dev_remove(gpointer user_data)
902 struct svc_callback *cb = user_data;
905 g_source_remove(cb->idle_id);
907 cb->func(cb->dev, -ENODEV, cb->user_data);
912 static void device_free(gpointer user_data)
914 struct btd_device *device = user_data;
916 btd_gatt_client_destroy(device->client_dbus);
917 device->client_dbus = NULL;
919 g_slist_free_full(device->uuids, g_free);
920 g_slist_free_full(device->primaries, g_free);
921 g_slist_free_full(device->svc_callbacks, svc_dev_remove);
923 /* Reset callbacks since the device is going to be freed */
924 gatt_db_unregister(device->db, device->db_id);
926 attio_cleanup(device);
928 gatt_db_unref(device->db);
930 bt_ad_unref(device->ad);
932 if (device->tmp_records)
933 sdp_list_free(device->tmp_records,
934 (sdp_free_func_t) sdp_record_free);
936 if (device->disconn_timer)
937 g_source_remove(device->disconn_timer);
939 if (device->discov_timer)
940 g_source_remove(device->discov_timer);
943 dbus_message_unref(device->connect);
945 if (device->disconnect)
946 dbus_message_unref(device->disconnect);
951 if (device->authr->agent)
952 agent_unref(device->authr->agent);
953 g_free(device->authr->pincode);
954 g_free(device->authr);
957 if (device->eir_uuids)
958 g_slist_free_full(device->eir_uuids, g_free);
960 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
963 g_free(device->local_csrk);
964 g_free(device->remote_csrk);
965 g_free(device->path);
966 g_free(device->alias);
967 free(device->modalias);
971 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
972 void device_set_remote_feature_flag(struct btd_device *device, int flags)
974 device->remote_feature_flags = flags;
977 gboolean device_is_bredrle(struct btd_device *device)
979 return (device->remote_feature_flags & (EIR_CONTROLLER | EIR_SIM_HOST));
983 bool device_is_paired(struct btd_device *device, uint8_t bdaddr_type)
985 struct bearer_state *state = get_state(device, bdaddr_type);
987 return state->paired;
990 bool device_is_bonded(struct btd_device *device, uint8_t bdaddr_type)
992 struct bearer_state *state = get_state(device, bdaddr_type);
994 return state->bonded;
997 gboolean device_is_trusted(struct btd_device *device)
999 return device->trusted;
1002 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1003 gboolean device_is_profile_trusted(struct btd_device *device,
1006 if (g_strcmp0(uuid, OBEX_PSE_UUID) == 0) {
1007 if (device->trusted_profiles.pbap == SUPPORTED_TRUSTED)
1009 } else if (g_strcmp0(uuid, OBEX_MAS_UUID) == 0) {
1010 if (device->trusted_profiles.map == SUPPORTED_TRUSTED)
1012 } else if (g_strcmp0(uuid, SAP_UUID) == 0) {
1013 if (device->trusted_profiles.sap == SUPPORTED_TRUSTED)
1015 } else if (g_strcmp0(uuid, HFP_HS_UUID) == 0) {
1016 if (device->trusted_profiles.hfp_hs == SUPPORTED_TRUSTED)
1018 } else if (g_strcmp0(uuid, A2DP_SINK_UUID) == 0) {
1019 if (device->trusted_profiles.a2dp == SUPPORTED_TRUSTED)
1025 gboolean device_is_profile_blocked(struct btd_device *device,
1028 if (g_strcmp0(uuid, OBEX_PSE_UUID) == 0) {
1029 if (device->trusted_profiles.pbap == SUPPORTED_BLOCKED)
1031 } else if (g_strcmp0(uuid, OBEX_MAS_UUID) == 0) {
1032 if (device->trusted_profiles.map == SUPPORTED_BLOCKED)
1034 } else if (g_strcmp0(uuid, SAP_UUID) == 0) {
1035 if (device->trusted_profiles.sap == SUPPORTED_BLOCKED)
1037 } else if (g_strcmp0(uuid, HFP_HS_UUID) == 0) {
1038 if (device->trusted_profiles.hfp_hs == SUPPORTED_BLOCKED)
1040 } else if (g_strcmp0(uuid, A2DP_SINK_UUID) == 0) {
1041 if (device->trusted_profiles.a2dp == SUPPORTED_BLOCKED)
1048 static gboolean dev_property_get_address(const GDBusPropertyTable *property,
1049 DBusMessageIter *iter, void *data)
1051 struct btd_device *device = data;
1053 const char *ptr = dstaddr;
1055 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1057 ba2str(device->rpa, dstaddr);
1060 ba2str(&device->bdaddr, dstaddr);
1061 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
1066 static gboolean property_get_address_type(const GDBusPropertyTable *property,
1067 DBusMessageIter *iter, void *user_data)
1069 struct btd_device *device = user_data;
1072 if (device->le && device->bdaddr_type == BDADDR_LE_RANDOM)
1077 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
1082 static gboolean dev_property_get_name(const GDBusPropertyTable *property,
1083 DBusMessageIter *iter, void *data)
1085 struct btd_device *device = data;
1086 const char *ptr = device->name;
1088 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
1093 static gboolean dev_property_exists_name(const GDBusPropertyTable *property,
1096 struct btd_device *dev = data;
1098 return device_name_known(dev);
1101 static gboolean dev_property_get_alias(const GDBusPropertyTable *property,
1102 DBusMessageIter *iter, void *data)
1104 struct btd_device *device = data;
1108 /* Alias (fallback to name or address) */
1109 if (device->alias != NULL)
1110 ptr = device->alias;
1111 else if (strlen(device->name) > 0) {
1114 ba2str(&device->bdaddr, dstaddr);
1115 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
1116 g_strdelimit(dstaddr, ":", '-');
1121 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
1126 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1127 static gboolean dev_property_get_alias_set(const GDBusPropertyTable *property,
1128 DBusMessageIter *iter, void *data)
1130 struct btd_device *device = data;
1133 if (device->alias != NULL)
1138 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1144 static void set_alias(GDBusPendingPropertySet id, const char *alias,
1147 struct btd_device *device = data;
1150 if ((device->alias == NULL && g_str_equal(alias, "")) ||
1151 g_strcmp0(device->alias, alias) == 0) {
1152 g_dbus_pending_property_success(id);
1156 g_free(device->alias);
1157 device->alias = g_str_equal(alias, "") ? NULL : g_strdup(alias);
1159 store_device_info(device);
1161 g_dbus_emit_property_changed(dbus_conn, device->path,
1162 DEVICE_INTERFACE, "Alias");
1164 g_dbus_pending_property_success(id);
1167 static void dev_property_set_alias(const GDBusPropertyTable *property,
1168 DBusMessageIter *value,
1169 GDBusPendingPropertySet id, void *data)
1173 if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_STRING) {
1174 g_dbus_pending_property_error(id,
1175 ERROR_INTERFACE ".InvalidArguments",
1176 "Invalid arguments in method call");
1180 dbus_message_iter_get_basic(value, &alias);
1182 set_alias(id, alias, data);
1185 static gboolean dev_property_exists_class(const GDBusPropertyTable *property,
1188 struct btd_device *device = data;
1190 return device->class != 0;
1193 static gboolean dev_property_get_class(const GDBusPropertyTable *property,
1194 DBusMessageIter *iter, void *data)
1196 struct btd_device *device = data;
1198 if (device->class == 0)
1201 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &device->class);
1206 static gboolean get_appearance(const GDBusPropertyTable *property, void *data,
1207 uint16_t *appearance)
1209 struct btd_device *device = data;
1211 if (dev_property_exists_class(property, data))
1214 if (device->appearance) {
1215 *appearance = device->appearance;
1222 static gboolean dev_property_exists_appearance(
1223 const GDBusPropertyTable *property, void *data)
1225 uint16_t appearance;
1227 return get_appearance(property, data, &appearance);
1230 static gboolean dev_property_get_appearance(const GDBusPropertyTable *property,
1231 DBusMessageIter *iter, void *data)
1233 uint16_t appearance;
1235 if (!get_appearance(property, data, &appearance))
1238 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &appearance);
1243 static const char *get_icon(const GDBusPropertyTable *property, void *data)
1245 struct btd_device *device = data;
1246 const char *icon = NULL;
1247 uint16_t appearance;
1249 if (device->class != 0)
1250 icon = class_to_icon(device->class);
1251 else if (get_appearance(property, data, &appearance))
1252 icon = gap_appearance_to_icon(appearance);
1257 static gboolean dev_property_exists_icon(
1258 const GDBusPropertyTable *property, void *data)
1260 return get_icon(property, data) != NULL;
1263 static gboolean dev_property_get_icon(const GDBusPropertyTable *property,
1264 DBusMessageIter *iter, void *data)
1268 icon = get_icon(property, data);
1272 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &icon);
1277 static gboolean dev_property_get_paired(const GDBusPropertyTable *property,
1278 DBusMessageIter *iter, void *data)
1280 struct btd_device *dev = data;
1283 if (dev->bredr_state.paired || dev->le_state.paired)
1288 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1293 static gboolean dev_property_get_legacy(const GDBusPropertyTable *property,
1294 DBusMessageIter *iter, void *data)
1296 struct btd_device *device = data;
1297 dbus_bool_t val = device->legacy;
1299 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1304 static gboolean dev_property_get_rssi(const GDBusPropertyTable *property,
1305 DBusMessageIter *iter, void *data)
1307 struct btd_device *dev = data;
1308 dbus_int16_t val = dev->rssi;
1310 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &val);
1315 static gboolean dev_property_exists_rssi(const GDBusPropertyTable *property,
1318 struct btd_device *dev = data;
1326 static gboolean dev_property_get_tx_power(const GDBusPropertyTable *property,
1327 DBusMessageIter *iter, void *data)
1329 struct btd_device *dev = data;
1330 dbus_int16_t val = dev->tx_power;
1332 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &val);
1337 static gboolean dev_property_exists_tx_power(const GDBusPropertyTable *property,
1340 struct btd_device *dev = data;
1342 if (dev->tx_power == 127)
1349 dev_property_get_svc_resolved(const GDBusPropertyTable *property,
1350 DBusMessageIter *iter, void *data)
1352 struct btd_device *device = data;
1353 gboolean val = device->svc_refreshed;
1355 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1360 static gboolean dev_property_flags_exist(const GDBusPropertyTable *property,
1363 struct btd_device *device = data;
1365 return device->ad_flags[0] != INVALID_FLAGS;
1369 dev_property_get_flags(const GDBusPropertyTable *property,
1370 DBusMessageIter *iter, void *data)
1372 struct btd_device *device = data;
1373 uint8_t *flags = device->ad_flags;
1374 DBusMessageIter array;
1376 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1377 DBUS_TYPE_BYTE_AS_STRING, &array);
1378 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
1379 &flags, sizeof(device->ad_flags));
1380 dbus_message_iter_close_container(iter, &array);
1385 static gboolean dev_property_get_trusted(const GDBusPropertyTable *property,
1386 DBusMessageIter *iter, void *data)
1388 struct btd_device *device = data;
1389 gboolean val = device_is_trusted(device);
1391 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
1396 static void set_trust(GDBusPendingPropertySet id, gboolean value, void *data)
1398 struct btd_device *device = data;
1400 btd_device_set_trusted(device, value);
1402 g_dbus_pending_property_success(id);
1405 static void dev_property_set_trusted(const GDBusPropertyTable *property,
1406 DBusMessageIter *value,
1407 GDBusPendingPropertySet id, void *data)
1411 if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
1412 g_dbus_pending_property_error(id,
1413 ERROR_INTERFACE ".InvalidArguments",
1414 "Invalid arguments in method call");
1418 dbus_message_iter_get_basic(value, &b);
1420 set_trust(id, b, data);
1423 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1424 static gboolean dev_property_get_trusted_profiles(const GDBusPropertyTable *property,
1425 DBusMessageIter *iter, void *data)
1427 struct btd_device *device = data;
1428 uint32_t pbap = device->trusted_profiles.pbap;
1429 uint32_t map = device->trusted_profiles.map;
1430 uint32_t sap = device->trusted_profiles.sap;
1431 uint32_t hfp_hs = device->trusted_profiles.hfp_hs;
1432 uint32_t a2dp = device->trusted_profiles.a2dp;
1434 unsigned int val = (pbap << PBAP_SHIFT_OFFSET) |
1435 (map << MAP_SHIFT_OFFSET) |
1436 (sap << SAP_SHIFT_OFFSET) |
1437 (hfp_hs << HFP_HS_SHIFT_OFFSET) |
1438 (a2dp << A2DP_SHIFT_OFFSET);
1440 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &val);
1446 static gboolean dev_property_get_blocked(const GDBusPropertyTable *property,
1447 DBusMessageIter *iter, void *data)
1449 struct btd_device *device = data;
1451 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
1457 static void set_blocked(GDBusPendingPropertySet id, gboolean value, void *data)
1459 struct btd_device *device = data;
1463 err = device_block(device, FALSE);
1465 err = device_unblock(device, FALSE, FALSE);
1469 g_dbus_pending_property_success(id);
1472 g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed",
1473 "Kernel lacks blacklist support");
1476 g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed",
1483 static void dev_property_set_blocked(const GDBusPropertyTable *property,
1484 DBusMessageIter *value,
1485 GDBusPendingPropertySet id, void *data)
1489 if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
1490 g_dbus_pending_property_error(id,
1491 ERROR_INTERFACE ".InvalidArguments",
1492 "Invalid arguments in method call");
1496 dbus_message_iter_get_basic(value, &b);
1498 set_blocked(id, b, data);
1501 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1502 static uint8_t device_get_connected_state(struct btd_device *device)
1504 if (device->bredr_state.connected && device->le_state.connected)
1505 return DEV_CONNECTED_BREDR_LE;
1506 else if (device->bredr_state.connected)
1507 return DEV_CONNECTED_BREDR;
1508 else if (device->le_state.connected)
1509 return DEV_CONNECTED_LE;
1511 return DEV_CONNECTED_NONE;
1514 static gboolean dev_property_get_payload(const GDBusPropertyTable *property,
1515 DBusMessageIter *iter, void *data)
1517 struct btd_device *dev = data;
1518 dbus_uint16_t payload_timeout = dev->auth_payload_timeout;
1520 dbus_message_iter_append_basic(iter,
1521 DBUS_TYPE_UINT16, &payload_timeout);
1526 static gboolean dev_property_get_last_addr_type(const GDBusPropertyTable *property,
1527 DBusMessageIter *iter, void *data)
1529 struct btd_device *dev = data;
1530 uint8_t last_addr_type = dev->last_bdaddr_type;
1532 dbus_message_iter_append_basic(iter,
1533 DBUS_TYPE_BYTE, &last_addr_type);
1538 static gboolean dev_property_get_att_mtu(const GDBusPropertyTable *property,
1539 DBusMessageIter *iter, void *data)
1541 struct btd_device *device = data;
1542 dbus_uint16_t mtu = bt_gatt_client_get_mtu(device->client);
1544 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &mtu);
1549 static gboolean dev_property_get_gatt_connected(const GDBusPropertyTable *property,
1550 DBusMessageIter *iter, void *data)
1552 struct btd_device *device = data;
1553 dbus_bool_t gatt_connected;
1555 if (device->gatt_connected)
1556 gatt_connected = TRUE;
1558 gatt_connected = FALSE;
1560 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN,
1566 static gboolean dev_property_get_ipsp_conn_state(const GDBusPropertyTable *property,
1567 DBusMessageIter *iter, void *data)
1569 struct btd_device *dev = data;
1570 dbus_bool_t ipsp_connected;
1572 if (dev->ipsp_connected)
1573 ipsp_connected = TRUE;
1575 ipsp_connected = FALSE;
1577 dbus_message_iter_append_basic(iter,
1578 DBUS_TYPE_BOOLEAN, &ipsp_connected);
1583 static gboolean dev_property_get_ipsp_conn_bt_iface_name(const GDBusPropertyTable *property,
1584 DBusMessageIter *iter, void *data)
1586 struct btd_device *dev = data;
1587 char *ptr = g_strdup(dev->if_name);
1589 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, (const char **)&ptr);
1597 static gboolean dev_property_get_connected(const GDBusPropertyTable *property,
1598 DBusMessageIter *iter, void *data)
1600 struct btd_device *dev = data;
1602 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1603 uint8_t connected = device_get_connected_state(dev);
1605 dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &connected);
1607 dbus_bool_t connected;
1609 if (dev->bredr_state.connected || dev->le_state.connected)
1614 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &connected);
1620 static gboolean dev_property_get_uuids(const GDBusPropertyTable *property,
1621 DBusMessageIter *iter, void *data)
1623 struct btd_device *dev = data;
1624 DBusMessageIter entry;
1627 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1628 DBUS_TYPE_STRING_AS_STRING, &entry);
1630 if (dev->bredr_state.svc_resolved || dev->le_state.svc_resolved)
1632 else if (dev->eir_uuids)
1637 for (; l != NULL; l = l->next)
1638 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
1641 dbus_message_iter_close_container(iter, &entry);
1646 static gboolean dev_property_get_modalias(const GDBusPropertyTable *property,
1647 DBusMessageIter *iter, void *data)
1649 struct btd_device *device = data;
1651 if (!device->modalias)
1654 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1660 static gboolean dev_property_exists_modalias(const GDBusPropertyTable *property,
1663 struct btd_device *device = data;
1665 return device->modalias ? TRUE : FALSE;
1668 static gboolean dev_property_get_adapter(const GDBusPropertyTable *property,
1669 DBusMessageIter *iter, void *data)
1671 struct btd_device *device = data;
1672 const char *str = adapter_get_path(device->adapter);
1674 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &str);
1679 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1680 static gboolean property_get_manufacturer_data_len(const GDBusPropertyTable *property,
1681 DBusMessageIter *iter, void *user_data)
1683 struct btd_device *device = user_data;
1684 dbus_uint16_t val = device->manufacturer_data_len;
1686 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &val);
1691 static gboolean property_get_manufacturer_data(const GDBusPropertyTable *property,
1692 DBusMessageIter *iter, void *user_data)
1694 struct btd_device *device = user_data;
1695 char str[DEV_MAX_MANUFACTURER_DATA_LEN] = {0};
1696 DBusMessageIter array;
1698 memset(str, 0, DEV_MAX_MANUFACTURER_DATA_LEN);
1699 if (device->manufacturer_data_len)
1700 memcpy(str, device->manufacturer_data,
1701 device->manufacturer_data_len);
1703 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1704 DBUS_TYPE_BYTE_AS_STRING, &array);
1706 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
1707 &device->manufacturer_data,
1708 device->manufacturer_data_len);
1710 dbus_message_iter_close_container(iter, &array);
1715 gboolean device_get_gatt_connected(const struct btd_device *device)
1717 return device->gatt_connected;
1721 static void append_manufacturer_data(void *data, void *user_data)
1723 struct bt_ad_manufacturer_data *md = data;
1724 DBusMessageIter *dict = user_data;
1726 g_dbus_dict_append_basic_array(dict,
1727 DBUS_TYPE_UINT16, &md->manufacturer_id,
1728 DBUS_TYPE_BYTE, &md->data, md->len);
1732 dev_property_get_manufacturer_data(const GDBusPropertyTable *property,
1733 DBusMessageIter *iter, void *data)
1735 struct btd_device *device = data;
1736 DBusMessageIter dict;
1738 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1739 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1740 DBUS_TYPE_UINT16_AS_STRING
1741 DBUS_TYPE_VARIANT_AS_STRING
1742 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1745 bt_ad_foreach_manufacturer_data(device->ad, append_manufacturer_data,
1748 dbus_message_iter_close_container(iter, &dict);
1754 dev_property_manufacturer_data_exist(const GDBusPropertyTable *property,
1757 struct btd_device *device = data;
1759 return bt_ad_has_manufacturer_data(device->ad, NULL);
1762 static void append_service_data(void *data, void *user_data)
1764 struct bt_ad_service_data *sd = data;
1765 DBusMessageIter *dict = user_data;
1766 char uuid_str[MAX_LEN_UUID_STR];
1768 bt_uuid_to_string(&sd->uuid, uuid_str, sizeof(uuid_str));
1770 dict_append_array(dict, uuid_str, DBUS_TYPE_BYTE, &sd->data, sd->len);
1774 dev_property_get_service_data(const GDBusPropertyTable *property,
1775 DBusMessageIter *iter, void *data)
1777 struct btd_device *device = data;
1778 DBusMessageIter dict;
1780 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1781 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1782 DBUS_TYPE_STRING_AS_STRING
1783 DBUS_TYPE_VARIANT_AS_STRING
1784 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1787 bt_ad_foreach_service_data(device->ad, append_service_data, &dict);
1789 dbus_message_iter_close_container(iter, &dict);
1795 dev_property_service_data_exist(const GDBusPropertyTable *property,
1798 struct btd_device *device = data;
1800 return bt_ad_has_service_data(device->ad, NULL);
1803 static void append_advertising_data(void *data, void *user_data)
1805 struct bt_ad_data *ad = data;
1806 DBusMessageIter *dict = user_data;
1808 g_dbus_dict_append_basic_array(dict,
1809 DBUS_TYPE_BYTE, &ad->type,
1810 DBUS_TYPE_BYTE, &ad->data, ad->len);
1814 dev_property_get_advertising_data(const GDBusPropertyTable *property,
1815 DBusMessageIter *iter, void *data)
1817 struct btd_device *device = data;
1818 DBusMessageIter dict;
1820 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1821 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1822 DBUS_TYPE_BYTE_AS_STRING
1823 DBUS_TYPE_VARIANT_AS_STRING
1824 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1827 bt_ad_foreach_data(device->ad, append_advertising_data, &dict);
1829 dbus_message_iter_close_container(iter, &dict);
1835 dev_property_advertising_data_exist(const GDBusPropertyTable *property,
1838 struct btd_device *device = data;
1840 return bt_ad_has_data(device->ad, NULL);
1843 static gboolean disconnect_all(gpointer user_data)
1845 struct btd_device *device = user_data;
1847 device->disconn_timer = 0;
1849 if (device->bredr_state.connected)
1850 btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
1853 if (device->le_state.connected)
1854 btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
1855 device->bdaddr_type);
1860 int device_block(struct btd_device *device, gboolean update_only)
1864 if (device->blocked)
1867 if (device->disconn_timer > 0)
1868 g_source_remove(device->disconn_timer);
1870 disconnect_all(device);
1872 while (device->services != NULL) {
1873 struct btd_service *service = device->services->data;
1875 device->services = g_slist_remove(device->services, service);
1876 service_remove(service);
1881 err = btd_adapter_block_address(device->adapter,
1883 device->bdaddr_type);
1884 if (!err && device->bredr)
1885 err = btd_adapter_block_address(device->adapter,
1893 device->blocked = TRUE;
1895 store_device_info(device);
1897 btd_device_set_temporary(device, false);
1899 g_dbus_emit_property_changed(dbus_conn, device->path,
1900 DEVICE_INTERFACE, "Blocked");
1905 int device_unblock(struct btd_device *device, gboolean silent,
1906 gboolean update_only)
1910 if (!device->blocked)
1915 err = btd_adapter_unblock_address(device->adapter,
1917 device->bdaddr_type);
1918 if (!err && device->bredr)
1919 err = btd_adapter_unblock_address(device->adapter,
1927 device->blocked = FALSE;
1929 store_device_info(device);
1932 g_dbus_emit_property_changed(dbus_conn, device->path,
1933 DEVICE_INTERFACE, "Blocked");
1934 device_probe_profiles(device, device->uuids);
1940 static void browse_request_exit(DBusConnection *conn, void *user_data)
1942 struct browse_req *req = user_data;
1944 DBG("Requestor exited");
1946 browse_request_cancel(req);
1949 static void bonding_request_cancel(struct bonding_req *bonding)
1951 struct btd_device *device = bonding->device;
1952 struct btd_adapter *adapter = device->adapter;
1954 adapter_cancel_bonding(adapter, &device->bdaddr, device->bdaddr_type);
1957 static void dev_disconn_service(gpointer a, gpointer b)
1959 btd_service_disconnect(a);
1962 void device_request_disconnect(struct btd_device *device, DBusMessage *msg)
1964 if (device->bonding)
1965 bonding_request_cancel(device->bonding);
1968 browse_request_cancel(device->browse);
1970 if (device->att_io) {
1971 g_io_channel_shutdown(device->att_io, FALSE, NULL);
1972 g_io_channel_unref(device->att_io);
1973 device->att_io = NULL;
1976 if (device->connect) {
1977 DBusMessage *reply = btd_error_failed(device->connect,
1979 g_dbus_send_message(dbus_conn, reply);
1980 dbus_message_unref(device->connect);
1981 device->connect = NULL;
1984 if (btd_device_is_connected(device) && msg)
1985 device->disconnects = g_slist_append(device->disconnects,
1986 dbus_message_ref(msg));
1988 if (device->disconn_timer)
1991 g_slist_foreach(device->services, dev_disconn_service, NULL);
1993 g_slist_free(device->pending);
1994 device->pending = NULL;
1996 while (device->watches) {
1997 struct btd_disconnect_data *data = device->watches->data;
2000 /* temporary is set if device is going to be removed */
2001 data->watch(device, device->temporary,
2004 /* Check if the watch has been removed by callback function */
2005 if (!g_slist_find(device->watches, data))
2008 device->watches = g_slist_remove(device->watches, data);
2012 if (!btd_device_is_connected(device)) {
2014 g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
2018 device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER,
2023 bool device_is_disconnecting(struct btd_device *device)
2025 return device->disconn_timer > 0;
2028 void device_set_ltk_enc_size(struct btd_device *device, uint8_t enc_size)
2030 device->ltk_enc_size = enc_size;
2031 bt_att_set_enc_key_size(device->att, device->ltk_enc_size);
2034 static void device_set_auto_connect(struct btd_device *device, gboolean enable)
2038 if (!device || !device->le)
2041 ba2str(&device->bdaddr, addr);
2043 DBG("%s auto connect: %d", addr, enable);
2045 if (device->auto_connect == enable)
2048 device->auto_connect = enable;
2050 /* Disabling auto connect */
2051 if (enable == FALSE) {
2052 adapter_connect_list_remove(device->adapter, device);
2053 adapter_auto_connect_remove(device->adapter, device);
2057 /* Enabling auto connect */
2058 adapter_auto_connect_add(device->adapter, device);
2060 if (device->attrib) {
2061 DBG("Already connected");
2065 adapter_connect_list_add(device->adapter, device);
2068 static DBusMessage *dev_disconnect(DBusConnection *conn, DBusMessage *msg,
2071 struct btd_device *device = user_data;
2074 * If device is not trusted disable connections through passive
2075 * scanning until Device1.Connect is called
2077 if (device->auto_connect && !device->trusted) {
2078 device->disable_auto_connect = TRUE;
2079 device_set_auto_connect(device, FALSE);
2082 device_request_disconnect(device, msg);
2087 static int connect_next(struct btd_device *dev)
2089 struct btd_service *service;
2092 while (dev->pending) {
2093 service = dev->pending->data;
2095 err = btd_service_connect(service);
2099 dev->pending = g_slist_delete_link(dev->pending, dev->pending);
2105 static void device_profile_connected(struct btd_device *dev,
2106 struct btd_profile *profile, int err)
2108 struct btd_service *pending;
2111 DBG("%s %s (%d)", profile->name, strerror(-err), -err);
2114 btd_device_set_temporary(dev, false);
2116 if (dev->pending == NULL)
2119 if (!btd_device_is_connected(dev)) {
2121 case EHOSTDOWN: /* page timeout */
2122 case EHOSTUNREACH: /* adapter not powered */
2123 case ECONNABORTED: /* adapter powered down */
2128 pending = dev->pending->data;
2129 l = find_service_with_profile(dev->pending, profile);
2131 dev->pending = g_slist_delete_link(dev->pending, l);
2133 /* Only continue connecting the next profile if it matches the first
2134 * pending, otherwise it will trigger another connect to the same
2137 if (profile != btd_service_get_profile(pending))
2140 if (connect_next(dev) == 0)
2144 g_slist_free(dev->pending);
2145 dev->pending = NULL;
2150 if (!err && dbus_message_is_method_call(dev->connect, DEVICE_INTERFACE,
2152 dev->general_connect = TRUE;
2154 DBG("returning response to %s", dbus_message_get_sender(dev->connect));
2156 l = find_service_with_state(dev->services, BTD_SERVICE_STATE_CONNECTED);
2158 if (err && l == NULL) {
2159 /* Fallback to LE bearer if supported */
2160 if (err == -EHOSTDOWN && dev->le && !dev->le_state.connected) {
2161 err = device_connect_le(dev);
2166 g_dbus_send_message(dbus_conn,
2167 btd_error_failed(dev->connect, strerror(-err)));
2169 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2170 /* SDP is not required for Samsung TV Power on */
2171 if (g_strcmp0(profile->name, "hid-device") == 0) {
2172 DBG("Skip SDP discovery.");
2175 /* Start passive SDP discovery to update known services */
2176 if (dev->bredr && !dev->svc_refreshed)
2177 device_browse_sdp(dev, NULL);
2178 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2182 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2184 g_dbus_send_message(dbus_conn,
2185 btd_error_failed(dev->connect, strerror(-err)));
2187 g_dbus_send_reply(dbus_conn, dev->connect, DBUS_TYPE_INVALID);
2189 g_dbus_send_reply(dbus_conn, dev->connect, DBUS_TYPE_INVALID);
2193 dbus_message_unref(dev->connect);
2194 dev->connect = NULL;
2197 void device_add_eir_uuids(struct btd_device *dev, GSList *uuids)
2202 if (dev->bredr_state.svc_resolved || dev->le_state.svc_resolved)
2205 for (l = uuids; l != NULL; l = l->next) {
2206 const char *str = l->data;
2207 if (g_slist_find_custom(dev->eir_uuids, str, bt_uuid_strcmp))
2210 dev->eir_uuids = g_slist_append(dev->eir_uuids, g_strdup(str));
2214 g_dbus_emit_property_changed(dbus_conn, dev->path,
2215 DEVICE_INTERFACE, "UUIDs");
2218 static void add_manufacturer_data(void *data, void *user_data)
2220 struct eir_msd *msd = data;
2221 struct btd_device *dev = user_data;
2223 if (!bt_ad_add_manufacturer_data(dev->ad, msd->company, msd->data,
2227 g_dbus_emit_property_changed(dbus_conn, dev->path,
2228 DEVICE_INTERFACE, "ManufacturerData");
2231 void device_set_manufacturer_data(struct btd_device *dev, GSList *list,
2235 bt_ad_clear_manufacturer_data(dev->ad);
2237 g_slist_foreach(list, add_manufacturer_data, dev);
2240 static void add_service_data(void *data, void *user_data)
2242 struct eir_sd *sd = data;
2243 struct btd_device *dev = user_data;
2246 if (bt_string_to_uuid(&uuid, sd->uuid) < 0)
2249 if (!bt_ad_add_service_data(dev->ad, &uuid, sd->data, sd->data_len))
2252 g_dbus_emit_property_changed(dbus_conn, dev->path,
2253 DEVICE_INTERFACE, "ServiceData");
2256 void device_set_service_data(struct btd_device *dev, GSList *list,
2260 bt_ad_clear_service_data(dev->ad);
2262 g_slist_foreach(list, add_service_data, dev);
2265 static void add_data(void *data, void *user_data)
2267 struct eir_ad *ad = data;
2268 struct btd_device *dev = user_data;
2270 if (!bt_ad_add_data(dev->ad, ad->type, ad->data, ad->len))
2273 if (ad->type == EIR_TRANSPORT_DISCOVERY)
2274 g_dbus_emit_property_changed(dbus_conn, dev->path,
2279 void device_set_data(struct btd_device *dev, GSList *list,
2283 bt_ad_clear_data(dev->ad);
2285 g_slist_foreach(list, add_data, dev);
2288 static struct btd_service *find_connectable_service(struct btd_device *dev,
2292 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2293 struct btd_service *s = NULL;
2295 for (l = dev->services; l != NULL; l = g_slist_next(l)) {
2296 struct btd_service *service = l->data;
2297 struct btd_profile *p = btd_service_get_profile(service);
2299 if (!p->connect || !p->remote_uuid)
2302 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
2303 if (strcasecmp(uuid, p->remote_uuid) == 0)
2306 if (strcasecmp(uuid, p->remote_uuid) == 0) {
2308 if (ext_profile_is_registered_as_client_role(p) == TRUE) {
2316 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2324 static int service_prio_cmp(gconstpointer a, gconstpointer b)
2326 struct btd_profile *p1 = btd_service_get_profile(a);
2327 struct btd_profile *p2 = btd_service_get_profile(b);
2329 return p2->priority - p1->priority;
2332 static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
2334 struct btd_service *service;
2335 struct btd_profile *p;
2337 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2338 bool hs_hf_verify = FALSE;
2342 service = find_connectable_service(dev, uuid);
2344 return g_slist_prepend(dev->pending, service);
2345 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2346 else if ((service == NULL) &&
2347 (g_strcmp0(uuid, HFP_HS_UUID) == 0)) {
2348 DBG("HFP service not found check for HSP service");
2349 service = find_connectable_service(dev, HSP_HS_UUID);
2351 return g_slist_prepend(dev->pending, service);
2352 } else if (g_strcmp0(uuid, HID_UUID) == 0) {
2353 DBG("HID service not found, add HID service");
2354 btd_device_add_uuid(dev, uuid);
2355 service = find_connectable_service(dev, HID_UUID);
2357 return g_slist_prepend(dev->pending, service);
2360 return dev->pending;
2363 for (l = dev->services; l != NULL; l = g_slist_next(l)) {
2365 p = btd_service_get_profile(service);
2367 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2368 DBG("profile uuid %s", p->remote_uuid);
2369 if (g_strcmp0(p->remote_uuid, HSP_HS_UUID) == 0) {
2370 DBG("HSP service is found check for HFP service");
2371 struct btd_service *service;
2372 struct btd_profile *p;
2375 for (h = dev->services; h != NULL; h = g_slist_next(h)) {
2377 p = btd_service_get_profile(service);
2379 if (g_strcmp0(p->remote_uuid, HFP_HS_UUID) == 0) {
2380 DBG("HFP found,ignore HSP ");
2381 hs_hf_verify = TRUE;
2389 if (!p->auto_connect)
2392 if (g_slist_find(dev->pending, service))
2395 if (btd_service_get_state(service) !=
2396 BTD_SERVICE_STATE_DISCONNECTED)
2399 dev->pending = g_slist_insert_sorted(dev->pending, service,
2403 return dev->pending;
2406 int btd_device_connect_services(struct btd_device *dev, GSList *services)
2410 if (dev->pending || dev->connect || dev->browse)
2413 if (!btd_adapter_get_powered(dev->adapter))
2416 if (!dev->bredr_state.svc_resolved)
2420 for (l = services; l; l = g_slist_next(l)) {
2421 struct btd_service *service = l->data;
2423 dev->pending = g_slist_append(dev->pending, service);
2426 dev->pending = create_pending_list(dev, NULL);
2429 return connect_next(dev);
2432 static DBusMessage *connect_profiles(struct btd_device *dev, uint8_t bdaddr_type,
2433 DBusMessage *msg, const char *uuid)
2435 struct bearer_state *state = get_state(dev, bdaddr_type);
2438 DBG("%s %s, client %s", dev->path, uuid ? uuid : "(all)",
2439 dbus_message_get_sender(msg));
2441 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2442 if (dev->pending || dev->connect)
2443 return btd_error_in_progress(msg);
2445 if (dev->pending || dev->connect || dev->browse)
2446 return btd_error_in_progress(msg);
2449 if (!btd_adapter_get_powered(dev->adapter))
2450 return btd_error_not_ready(msg);
2452 btd_device_set_temporary(dev, false);
2454 if (!state->svc_resolved)
2455 goto resolve_services;
2457 dev->pending = create_pending_list(dev, uuid);
2458 if (!dev->pending) {
2459 if (dev->svc_refreshed) {
2460 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2461 if (!uuid && find_service_with_state(dev->services,
2462 BTD_SERVICE_STATE_CONNECTED))
2464 if (find_service_with_state(dev->services,
2465 BTD_SERVICE_STATE_CONNECTED))
2467 return dbus_message_new_method_return(msg);
2469 return btd_error_not_available(msg);
2472 goto resolve_services;
2475 err = connect_next(dev);
2477 if (err == -EALREADY)
2478 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2479 return btd_error_already_connected(msg);
2481 return dbus_message_new_method_return(msg);
2483 return btd_error_failed(msg, strerror(-err));
2486 dev->connect = dbus_message_ref(msg);
2491 DBG("Resolving services for %s", dev->path);
2493 if (bdaddr_type == BDADDR_BREDR)
2494 err = device_browse_sdp(dev, msg);
2496 err = device_browse_gatt(dev, msg);
2498 return btd_error_failed(msg, strerror(-err));
2503 #define NVAL_TIME ((time_t) -1)
2504 #define SEEN_TRESHHOLD 300
2506 static uint8_t select_conn_bearer(struct btd_device *dev)
2508 time_t bredr_last = NVAL_TIME, le_last = NVAL_TIME;
2509 time_t current = time(NULL);
2511 /* Prefer bonded bearer in case only one is bonded */
2512 if (dev->bredr_state.bonded && !dev->le_state.bonded )
2513 return BDADDR_BREDR;
2514 else if (!dev->bredr_state.bonded && dev->le_state.bonded)
2515 return dev->bdaddr_type;
2517 /* If the address is random it can only be connected over LE */
2518 if (dev->bdaddr_type == BDADDR_LE_RANDOM)
2519 return dev->bdaddr_type;
2521 if (dev->bredr_seen) {
2522 bredr_last = current - dev->bredr_seen;
2523 if (bredr_last > SEEN_TRESHHOLD)
2524 bredr_last = NVAL_TIME;
2528 le_last = current - dev->le_seen;
2529 if (le_last > SEEN_TRESHHOLD)
2530 le_last = NVAL_TIME;
2533 if (le_last == NVAL_TIME && bredr_last == NVAL_TIME)
2534 return dev->bdaddr_type;
2536 if (dev->bredr && (!dev->le || le_last == NVAL_TIME))
2537 return BDADDR_BREDR;
2539 if (dev->le && (!dev->bredr || bredr_last == NVAL_TIME))
2540 return dev->bdaddr_type;
2543 * Prefer BR/EDR if time is the same since it might be from an
2544 * advertisement with BR/EDR flag set.
2546 if (bredr_last <= le_last && btd_adapter_get_bredr(dev->adapter))
2547 return BDADDR_BREDR;
2549 return dev->bdaddr_type;
2552 static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
2555 struct btd_device *dev = user_data;
2556 uint8_t bdaddr_type;
2558 if (dev->bredr_state.connected) {
2560 * Check if services have been resolved and there is at list
2561 * one connected before switching to connect LE.
2563 if (dev->bredr_state.svc_resolved &&
2564 find_service_with_state(dev->services,
2565 BTD_SERVICE_STATE_CONNECTED))
2566 bdaddr_type = dev->bdaddr_type;
2568 bdaddr_type = BDADDR_BREDR;
2569 } else if (dev->le_state.connected && dev->bredr)
2570 bdaddr_type = BDADDR_BREDR;
2572 bdaddr_type = select_conn_bearer(dev);
2574 if (bdaddr_type != BDADDR_BREDR) {
2577 if (dev->le_state.connected)
2578 return dbus_message_new_method_return(msg);
2580 btd_device_set_temporary(dev, false);
2582 if (dev->disable_auto_connect) {
2583 dev->disable_auto_connect = FALSE;
2584 device_set_auto_connect(dev, TRUE);
2587 err = device_connect_le(dev);
2589 return btd_error_failed(msg, strerror(-err));
2591 dev->connect = dbus_message_ref(msg);
2596 return connect_profiles(dev, bdaddr_type, msg, NULL);
2599 static DBusMessage *connect_profile(DBusConnection *conn, DBusMessage *msg,
2602 struct btd_device *dev = user_data;
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);
2612 reply = connect_profiles(dev, BDADDR_BREDR, msg, uuid);
2618 static void device_profile_disconnected(struct btd_device *dev,
2619 struct btd_profile *profile, int err)
2621 if (!dev->disconnect)
2625 g_dbus_send_message(dbus_conn,
2626 btd_error_failed(dev->disconnect,
2629 g_dbus_send_reply(dbus_conn, dev->disconnect,
2632 dbus_message_unref(dev->disconnect);
2633 dev->disconnect = NULL;
2636 static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
2639 struct btd_device *dev = user_data;
2640 struct btd_service *service;
2641 const char *pattern;
2645 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
2647 return btd_error_invalid_args(msg);
2649 uuid = bt_name2string(pattern);
2651 return btd_error_invalid_args(msg);
2653 service = find_connectable_service(dev, uuid);
2654 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2655 if ((service == NULL) && (g_strcmp0(uuid, HFP_HS_UUID) == 0)) {
2656 DBG("HFP service is not found check for HSP service");
2657 service = find_connectable_service(dev, HSP_HS_UUID);
2663 return btd_error_invalid_args(msg);
2665 if (dev->disconnect)
2666 return btd_error_in_progress(msg);
2668 dev->disconnect = dbus_message_ref(msg);
2670 err = btd_service_disconnect(service);
2674 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2675 if (dev->disconnect)
2677 dbus_message_unref(dev->disconnect);
2678 dev->disconnect = NULL;
2680 if (err == -ENOTSUP)
2681 return btd_error_not_supported(msg);
2683 return btd_error_failed(msg, strerror(-err));
2686 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2687 static DBusMessage *disconnect_ext_profile(DBusConnection *conn,
2688 DBusMessage *msg, void *user_data)
2690 struct btd_device *dev = user_data;
2691 struct btd_profile *profile;
2692 struct btd_service *service;
2693 const char *sender, *path;
2697 sender = dbus_message_get_sender(msg);
2699 DBG("sender %s", sender);
2701 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
2703 return btd_error_invalid_args(msg);
2705 profile = btd_profile_find_ext(sender, path);
2707 return btd_error_invalid_args(msg);
2709 l = find_service_with_profile(dev->services, profile);
2711 return btd_error_invalid_args(msg);
2715 if (dev->disconnect)
2716 return btd_error_in_progress(msg);
2718 dev->disconnect = dbus_message_ref(msg);
2720 err = btd_service_disconnect(service);
2724 if (dev->disconnect)
2725 dbus_message_unref(dev->disconnect);
2726 dev->disconnect = NULL;
2728 if (err == -ENOTSUP)
2729 return btd_error_not_supported(msg);
2731 return btd_error_failed(msg, strerror(-err));
2735 static void store_services(struct btd_device *device)
2737 char filename[PATH_MAX];
2746 if (device_address_is_private(device)) {
2747 DBG("Can't store services for private addressed device %s",
2752 sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
2753 prim_uuid = bt_uuid2string(&uuid);
2754 if (prim_uuid == NULL)
2757 ba2str(&device->bdaddr, dst_addr);
2759 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2761 ba2str(device->rpa, dst_addr);
2764 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes",
2765 btd_adapter_get_storage_dir(device->adapter),
2767 key_file = g_key_file_new();
2769 for (l = device->primaries; l; l = l->next) {
2770 struct gatt_primary *primary = l->data;
2771 char handle[6], uuid_str[33];
2774 sprintf(handle, "%hu", primary->range.start);
2776 bt_string2uuid(&uuid, primary->uuid);
2777 sdp_uuid128_to_uuid(&uuid);
2779 switch (uuid.type) {
2781 sprintf(uuid_str, "%4.4X", uuid.value.uuid16);
2784 sprintf(uuid_str, "%8.8X", uuid.value.uuid32);
2787 for (i = 0; i < 16; i++)
2788 sprintf(uuid_str + (i * 2), "%2.2X",
2789 uuid.value.uuid128.data[i]);
2795 g_key_file_set_string(key_file, handle, "UUID", prim_uuid);
2796 g_key_file_set_string(key_file, handle, "Value", uuid_str);
2797 g_key_file_set_integer(key_file, handle, "EndGroupHandle",
2798 primary->range.end);
2801 data = g_key_file_to_data(key_file, &length, NULL);
2803 create_file(filename, S_IRUSR | S_IWUSR);
2804 g_file_set_contents(filename, data, length, NULL);
2809 g_key_file_free(key_file);
2813 struct btd_device *device;
2818 static void db_hash_read_value_cb(struct gatt_db_attribute *attrib,
2819 int err, const uint8_t *value,
2820 size_t length, void *user_data)
2822 const uint8_t **hash = user_data;
2824 if (err || (length != 16))
2830 static void store_desc(struct gatt_db_attribute *attr, void *user_data)
2832 struct gatt_saver *saver = user_data;
2833 GKeyFile *key_file = saver->key_file;
2834 char handle[6], value[100], uuid_str[MAX_LEN_UUID_STR];
2835 const bt_uuid_t *uuid;
2837 uint16_t handle_num;
2839 handle_num = gatt_db_attribute_get_handle(attr);
2840 sprintf(handle, "%04hx", handle_num);
2842 uuid = gatt_db_attribute_get_type(attr);
2843 bt_uuid_to_string(uuid, uuid_str, sizeof(uuid_str));
2845 bt_uuid16_create(&ext_uuid, GATT_CHARAC_EXT_PROPER_UUID);
2846 if (!bt_uuid_cmp(uuid, &ext_uuid) && saver->ext_props)
2847 sprintf(value, "%04hx:%s", saver->ext_props, uuid_str);
2849 sprintf(value, "%s", uuid_str);
2851 g_key_file_set_string(key_file, "Attributes", handle, value);
2854 static void store_chrc(struct gatt_db_attribute *attr, void *user_data)
2856 struct gatt_saver *saver = user_data;
2857 GKeyFile *key_file = saver->key_file;
2858 char handle[6], value[100], uuid_str[MAX_LEN_UUID_STR];
2859 uint16_t handle_num, value_handle;
2861 bt_uuid_t uuid, hash_uuid;
2863 if (!gatt_db_attribute_get_char_data(attr, &handle_num, &value_handle,
2864 &properties, &saver->ext_props,
2866 warn("Error storing characteristic - can't get data");
2870 sprintf(handle, "%04hx", handle_num);
2871 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
2873 /* Store Database Hash value if available */
2874 bt_uuid16_create(&hash_uuid, GATT_CHARAC_DB_HASH);
2875 if (!bt_uuid_cmp(&uuid, &hash_uuid)) {
2876 const uint8_t *hash = NULL;
2878 attr = gatt_db_get_attribute(saver->device->db, value_handle);
2880 gatt_db_attribute_read(attr, 0, BT_ATT_OP_READ_REQ, NULL,
2881 db_hash_read_value_cb, &hash);
2883 sprintf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hhx:"
2884 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
2885 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
2886 "%02hhx%02hhx:%s", value_handle, properties,
2887 hash[0], hash[1], hash[2], hash[3],
2888 hash[4], hash[5], hash[6], hash[7],
2889 hash[8], hash[9], hash[10], hash[11],
2890 hash[12], hash[13], hash[14], hash[15],
2893 sprintf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hhx:%s",
2894 value_handle, properties, uuid_str);
2897 sprintf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hhx:%s",
2898 value_handle, properties, uuid_str);
2900 g_key_file_set_string(key_file, "Attributes", handle, value);
2902 gatt_db_service_foreach_desc(attr, store_desc, saver);
2905 static void store_incl(struct gatt_db_attribute *attr, void *user_data)
2907 struct gatt_saver *saver = user_data;
2908 GKeyFile *key_file = saver->key_file;
2909 struct gatt_db_attribute *service;
2910 char handle[6], value[100], uuid_str[MAX_LEN_UUID_STR];
2911 uint16_t handle_num, start, end;
2914 if (!gatt_db_attribute_get_incl_data(attr, &handle_num, &start, &end)) {
2915 warn("Error storing included service - can't get data");
2919 service = gatt_db_get_attribute(saver->device->db, start);
2921 warn("Error storing included service - can't find it");
2925 sprintf(handle, "%04hx", handle_num);
2927 gatt_db_attribute_get_service_uuid(service, &uuid);
2928 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
2929 sprintf(value, GATT_INCLUDE_UUID_STR ":%04hx:%04hx:%s", start,
2932 g_key_file_set_string(key_file, "Attributes", handle, value);
2935 static void store_service(struct gatt_db_attribute *attr, void *user_data)
2937 struct gatt_saver *saver = user_data;
2938 GKeyFile *key_file = saver->key_file;
2939 char uuid_str[MAX_LEN_UUID_STR], handle[6], value[256];
2940 uint16_t start, end;
2945 if (!gatt_db_attribute_get_service_data(attr, &start, &end, &primary,
2947 warn("Error storing service - can't get data");
2951 sprintf(handle, "%04hx", start);
2953 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
2956 type = GATT_PRIM_SVC_UUID_STR;
2958 type = GATT_SND_SVC_UUID_STR;
2960 sprintf(value, "%s:%04hx:%s", type, end, uuid_str);
2962 g_key_file_set_string(key_file, "Attributes", handle, value);
2964 gatt_db_service_foreach_incl(attr, store_incl, saver);
2965 gatt_db_service_foreach_char(attr, store_chrc, saver);
2968 static void store_gatt_db(struct btd_device *device)
2970 char filename[PATH_MAX];
2975 struct gatt_saver saver;
2977 if (device_address_is_private(device)) {
2978 DBG("Can't store GATT db for private addressed device %s",
2983 if (!gatt_cache_is_enabled(device))
2986 ba2str(&device->bdaddr, dst_addr);
2988 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
2989 btd_adapter_get_storage_dir(device->adapter),
2991 create_file(filename, S_IRUSR | S_IWUSR);
2993 key_file = g_key_file_new();
2994 g_key_file_load_from_file(key_file, filename, 0, NULL);
2996 /* Remove current attributes since it might have changed */
2997 g_key_file_remove_group(key_file, "Attributes", NULL);
2999 saver.key_file = key_file;
3000 saver.device = device;
3002 gatt_db_foreach_service(device->db, NULL, store_service, &saver);
3004 data = g_key_file_to_data(key_file, &length, NULL);
3005 g_file_set_contents(filename, data, length, NULL);
3008 g_key_file_free(key_file);
3012 static void browse_request_complete(struct browse_req *req, uint8_t type,
3013 uint8_t bdaddr_type, int err)
3015 struct btd_device *dev = req->device;
3016 DBusMessage *reply = NULL;
3019 if (req->type != type)
3025 if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE, "Pair")) {
3026 if (!device_is_paired(dev, bdaddr_type)) {
3027 reply = btd_error_failed(req->msg, "Not paired");
3031 if (dev->pending_paired) {
3032 g_dbus_emit_property_changed(dbus_conn, dev->path,
3033 DEVICE_INTERFACE, "Paired");
3034 dev->pending_paired = false;
3037 /* Disregard browse errors in case of Pair */
3038 reply = g_dbus_create_reply(req->msg, DBUS_TYPE_INVALID);
3043 /* Fallback to LE bearer if supported */
3044 if (err == -EHOSTDOWN && bdaddr_type == BDADDR_BREDR &&
3045 dev->le && !dev->le_state.connected) {
3046 err = device_connect_le(dev);
3050 reply = btd_error_failed(req->msg, strerror(-err));
3054 /* if successfully resolved services we need to free browsing request
3055 * before passing message back to connect functions, otherwise
3056 * device->browse is set and "InProgress" error is returned instead
3057 * of actually connecting services
3059 msg = dbus_message_ref(req->msg);
3060 browse_request_free(req);
3063 if (dbus_message_is_method_call(msg, DEVICE_INTERFACE, "Connect"))
3064 reply = dev_connect(dbus_conn, msg, dev);
3065 else if (dbus_message_is_method_call(msg, DEVICE_INTERFACE,
3067 reply = connect_profile(dbus_conn, msg, dev);
3069 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3071 dbus_message_unref(msg);
3075 g_dbus_send_message(dbus_conn, reply);
3078 browse_request_free(req);
3081 static void device_set_svc_refreshed(struct btd_device *device, bool value)
3083 if (device->svc_refreshed == value)
3086 device->svc_refreshed = value;
3088 g_dbus_emit_property_changed(dbus_conn, device->path,
3089 DEVICE_INTERFACE, "ServicesResolved");
3092 static void device_svc_resolved(struct btd_device *dev, uint8_t browse_type,
3093 uint8_t bdaddr_type, int err)
3095 struct bearer_state *state = get_state(dev, bdaddr_type);
3096 struct browse_req *req = dev->browse;
3098 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3099 DBG("%s bdaddr_type %d err %d", dev->path, bdaddr_type, err);
3101 DBG("%s err %d", dev->path, err);
3104 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3105 state->svc_resolved = true;
3108 state->svc_resolved = true;
3111 /* Disconnection notification can happen before this function
3112 * gets called, so don't set svc_refreshed for a disconnected
3115 if (state->connected)
3116 device_set_svc_refreshed(dev, true);
3118 g_slist_free_full(dev->eir_uuids, g_free);
3119 dev->eir_uuids = NULL;
3121 if (dev->pending_paired) {
3122 g_dbus_emit_property_changed(dbus_conn, dev->path,
3123 DEVICE_INTERFACE, "Paired");
3124 dev->pending_paired = false;
3127 if (!dev->temporary) {
3128 store_device_info(dev);
3130 if (bdaddr_type != BDADDR_BREDR && err == 0)
3131 store_services(dev);
3134 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3136 browse_request_complete(req, browse_type, bdaddr_type, err);
3139 while (dev->svc_callbacks) {
3140 struct svc_callback *cb = dev->svc_callbacks->data;
3142 if (cb->idle_id > 0)
3143 g_source_remove(cb->idle_id);
3145 cb->func(dev, err, cb->user_data);
3147 dev->svc_callbacks = g_slist_delete_link(dev->svc_callbacks,
3148 dev->svc_callbacks);
3152 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3156 /* If bdaddr_type is LE but req is for SDP, don't complete browse req. */
3157 if (bdaddr_type != BDADDR_BREDR && req->search_uuid) {
3158 DBG("Discover comp. is for LE but browse req. is for SDP.");
3162 browse_request_complete(req, browse_type, bdaddr_type, err);
3166 static struct bonding_req *bonding_request_new(DBusMessage *msg,
3167 struct btd_device *device,
3168 uint8_t bdaddr_type,
3169 struct agent *agent)
3171 struct bonding_req *bonding;
3174 ba2str(&device->bdaddr, addr);
3175 DBG("Requesting bonding for %s", addr);
3177 bonding = g_new0(struct bonding_req, 1);
3179 bonding->msg = dbus_message_ref(msg);
3180 bonding->bdaddr_type = bdaddr_type;
3182 bonding->cb_iter = btd_adapter_pin_cb_iter_new(device->adapter);
3184 /* Marks the bonding start time for the first attempt on request
3185 * construction. The following attempts will be updated on
3186 * device_bonding_retry. */
3187 clock_gettime(CLOCK_MONOTONIC, &bonding->attempt_start_time);
3190 bonding->agent = agent_ref(agent);
3195 void device_bonding_restart_timer(struct btd_device *device)
3197 if (!device || !device->bonding)
3200 clock_gettime(CLOCK_MONOTONIC, &device->bonding->attempt_start_time);
3203 static void bonding_request_stop_timer(struct bonding_req *bonding)
3205 struct timespec current;
3207 clock_gettime(CLOCK_MONOTONIC, ¤t);
3209 /* Compute the time difference in ms. */
3210 bonding->last_attempt_duration_ms =
3211 (current.tv_sec - bonding->attempt_start_time.tv_sec) * 1000L +
3212 (current.tv_nsec - bonding->attempt_start_time.tv_nsec)
3216 /* Returns the duration of the last bonding attempt in milliseconds. The
3217 * duration is measured starting from the latest of the following three
3218 * events and finishing when the Command complete event is received for the
3219 * authentication request:
3220 * - MGMT_OP_PAIR_DEVICE is sent,
3221 * - MGMT_OP_PIN_CODE_REPLY is sent and
3222 * - Command complete event is received for the sent MGMT_OP_PIN_CODE_REPLY.
3224 long device_bonding_last_duration(struct btd_device *device)
3226 struct bonding_req *bonding = device->bonding;
3231 return bonding->last_attempt_duration_ms;
3234 static void create_bond_req_exit(DBusConnection *conn, void *user_data)
3236 struct btd_device *device = user_data;
3239 ba2str(&device->bdaddr, addr);
3240 DBG("%s: requestor exited before bonding was completed", addr);
3243 device_cancel_authentication(device, FALSE);
3245 if (device->bonding) {
3246 device->bonding->listener_id = 0;
3247 device_request_disconnect(device, NULL);
3251 static void bonding_request_free(struct bonding_req *bonding)
3256 if (bonding->listener_id)
3257 g_dbus_remove_watch(dbus_conn, bonding->listener_id);
3260 dbus_message_unref(bonding->msg);
3262 if (bonding->cb_iter)
3263 g_free(bonding->cb_iter);
3265 if (bonding->agent) {
3266 agent_cancel(bonding->agent);
3267 agent_unref(bonding->agent);
3268 bonding->agent = NULL;
3271 if (bonding->retry_timer)
3272 g_source_remove(bonding->retry_timer);
3274 if (bonding->device)
3275 bonding->device->bonding = NULL;
3280 static DBusMessage *pair_device(DBusConnection *conn, DBusMessage *msg,
3283 struct btd_device *device = data;
3284 struct btd_adapter *adapter = device->adapter;
3285 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3286 struct bearer_state *state;
3288 uint8_t bdaddr_type;
3290 struct agent *agent;
3291 struct bonding_req *bonding;
3293 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3295 bool connect_le = FALSE;
3296 uint8_t link_type = DEV_CONNECTED_NONE;
3300 btd_device_set_temporary(device, false);
3302 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3303 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_BYTE, &conn_type,
3304 DBUS_TYPE_INVALID) == FALSE)
3306 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID))
3308 return btd_error_invalid_args(msg);
3310 if (device->bonding)
3311 return btd_error_in_progress(msg);
3313 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3314 if (conn_type == DEV_CONN_DEFAULT) {
3315 link_type = device_get_connected_state(device);
3317 if (link_type == DEV_CONNECTED_BREDR) {
3318 if (device_is_bonded(device, DEV_CONN_BREDR))
3319 return btd_error_already_exists(msg);
3320 conn_type = DEV_CONN_BREDR;
3321 } else if (link_type == DEV_CONNECTED_LE) {
3322 if (device_is_bonded(device, DEV_CONN_LE))
3323 return btd_error_already_exists(msg);
3324 conn_type = DEV_CONN_LE;
3326 if (device_is_bonded(device, DEV_CONN_BREDR))
3327 return btd_error_already_exists(msg);
3328 else if (device_is_bonded(device, DEV_CONN_LE))
3329 return btd_error_already_exists(msg);
3332 conn_type = DEV_CONN_BREDR;
3333 else if (device->le)
3334 conn_type = DEV_CONN_LE;
3336 conn_type = DEV_CONN_BREDR;
3339 if (device_is_bonded(device, conn_type))
3340 return btd_error_already_exists(msg);
3342 bdaddr_type = device->bdaddr_type;
3344 if (device->bredr_state.bonded)
3345 bdaddr_type = device->bdaddr_type;
3346 else if (device->le_state.bonded)
3347 bdaddr_type = BDADDR_BREDR;
3349 bdaddr_type = select_conn_bearer(device);
3351 state = get_state(device, bdaddr_type);
3354 return btd_error_already_exists(msg);
3357 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3358 DBG("conn_type %d, link_type %d, bdaddr_type %d, device->bredr %d",
3359 conn_type, link_type, bdaddr_type, device->bredr);
3360 if (conn_type == DEV_CONN_LE &&
3361 (device_is_bredrle(device) || bdaddr_type != BDADDR_BREDR)) {
3362 DBG("LE Connect request");
3367 sender = dbus_message_get_sender(msg);
3369 agent = agent_get(sender);
3371 io_cap = agent_get_io_capability(agent);
3373 io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
3375 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3376 if ((conn_type == DEV_CONN_LE && bdaddr_type != BDADDR_BREDR) ||
3378 bonding = bonding_request_new(msg, device, bdaddr_type, agent);
3380 bonding = bonding_request_new(msg, device, BDADDR_BREDR, agent);
3382 bonding = bonding_request_new(msg, device, bdaddr_type, agent);
3388 bonding->listener_id = g_dbus_add_disconnect_watch(dbus_conn,
3389 sender, create_bond_req_exit,
3392 device->bonding = bonding;
3393 bonding->device = device;
3395 /* Due to a bug in the kernel we might loose out on ATT commands
3396 * that arrive during the SMP procedure, so connect the ATT
3397 * channel first and only then start pairing (there's code for
3398 * this in the ATT connect callback)
3400 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3401 if (((conn_type == DEV_CONN_LE && bdaddr_type != BDADDR_BREDR) ||
3402 (connect_le)) && !device->le_state.connected)
3403 err = device_connect_le(device);
3404 else if (connect_le) /* Send bonding request if LE is already connected*/
3405 err = adapter_create_bonding(adapter, &device->bdaddr,
3406 bdaddr_type, io_cap);
3408 err = adapter_create_bonding(adapter, &device->bdaddr,
3409 BDADDR_BREDR, io_cap);
3411 if (bdaddr_type != BDADDR_BREDR) {
3412 if (!state->connected && btd_le_connect_before_pairing())
3413 err = device_connect_le(device);
3415 err = adapter_create_bonding(adapter, &device->bdaddr,
3416 device->bdaddr_type,
3419 err = adapter_create_bonding(adapter, &device->bdaddr,
3420 BDADDR_BREDR, io_cap);
3425 bonding_request_free(device->bonding);
3426 return btd_error_failed(msg, strerror(-err));
3432 static DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
3435 case MGMT_STATUS_SUCCESS:
3436 return dbus_message_new_method_return(msg);
3438 case MGMT_STATUS_CONNECT_FAILED:
3439 return dbus_message_new_error(msg,
3440 ERROR_INTERFACE ".ConnectionAttemptFailed",
3442 case MGMT_STATUS_TIMEOUT:
3443 return dbus_message_new_error(msg,
3444 ERROR_INTERFACE ".AuthenticationTimeout",
3445 "Authentication Timeout");
3446 case MGMT_STATUS_BUSY:
3447 case MGMT_STATUS_REJECTED:
3448 return dbus_message_new_error(msg,
3449 ERROR_INTERFACE ".AuthenticationRejected",
3450 "Authentication Rejected");
3451 case MGMT_STATUS_CANCELLED:
3452 case MGMT_STATUS_NO_RESOURCES:
3453 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
3454 case MGMT_STATUS_DISCONNECTED:
3456 return dbus_message_new_error(msg,
3457 ERROR_INTERFACE ".AuthenticationCanceled",
3458 "Authentication Canceled");
3459 case MGMT_STATUS_ALREADY_PAIRED:
3460 return dbus_message_new_error(msg,
3461 ERROR_INTERFACE ".AlreadyExists",
3464 return dbus_message_new_error(msg,
3465 ERROR_INTERFACE ".AuthenticationFailed",
3466 "Authentication Failed");
3470 static void device_cancel_bonding(struct btd_device *device, uint8_t status)
3472 struct bonding_req *bonding = device->bonding;
3479 ba2str(&device->bdaddr, addr);
3480 DBG("Canceling bonding request for %s", addr);
3483 device_cancel_authentication(device, FALSE);
3485 reply = new_authentication_return(bonding->msg, status);
3486 g_dbus_send_message(dbus_conn, reply);
3488 bonding_request_cancel(bonding);
3489 bonding_request_free(bonding);
3492 static DBusMessage *cancel_pairing(DBusConnection *conn, DBusMessage *msg,
3495 struct btd_device *device = data;
3496 struct bonding_req *req = device->bonding;
3501 return btd_error_does_not_exist(msg);
3503 device_cancel_bonding(device, MGMT_STATUS_CANCELLED);
3505 return dbus_message_new_method_return(msg);
3508 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3509 static DBusMessage *discover_services(DBusConnection *conn,
3510 DBusMessage *msg, void *user_data)
3512 struct btd_device *device = user_data;
3513 const char *pattern;
3517 return btd_error_in_progress(msg);
3519 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
3520 DBUS_TYPE_INVALID) == FALSE)
3521 return btd_error_invalid_args(msg);
3523 err = device_browse_sdp(device, msg);
3530 return btd_error_failed(msg,
3531 "Unable to search the SDP services");
3534 static const char *browse_request_get_requestor(struct browse_req *req)
3539 return dbus_message_get_sender(req->msg);
3542 static void iter_append_record(DBusMessageIter *dict, uint32_t handle,
3545 DBusMessageIter entry;
3547 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
3550 dbus_message_iter_append_basic(&entry, DBUS_TYPE_UINT32, &handle);
3552 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &record);
3554 dbus_message_iter_close_container(dict, &entry);
3557 static void discover_services_reply(struct browse_req *req, int err,
3561 DBusMessageIter iter, dict;
3570 if (err == -EHOSTDOWN)
3571 err_if = ERROR_INTERFACE ".ConnectionAttemptFailed";
3573 err_if = ERROR_INTERFACE ".Failed";
3575 reply = dbus_message_new_error(req->msg, err_if,
3577 g_dbus_send_message(dbus_conn, reply);
3581 reply = dbus_message_new_method_return(req->msg);
3585 dbus_message_iter_init_append(reply, &iter);
3587 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
3588 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
3589 DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_STRING_AS_STRING
3590 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
3592 for (seq = recs; seq; seq = seq->next) {
3593 sdp_record_t *rec = (sdp_record_t *) seq->data;
3599 result = g_string_new(NULL);
3601 convert_sdp_record_to_xml(rec, result,
3602 (void *) g_string_append);
3605 if (!g_utf8_validate(result->str, -1, NULL)) {
3608 DBG("UTF8 invalid string, make valid");
3609 ptr = g_utf8_make_valid(result->str, -1);
3610 iter_append_record(&dict, rec->handle, ptr);
3613 iter_append_record(&dict, rec->handle, result->str);
3617 g_string_free(result, TRUE);
3620 dbus_message_iter_close_container(&iter, &dict);
3622 g_dbus_send_message(dbus_conn, reply);
3625 static DBusMessage *cancel_discover(DBusConnection *conn,
3626 DBusMessage *msg, void *user_data)
3628 struct btd_device *device = user_data;
3629 const char *sender = dbus_message_get_sender(msg);
3630 const char *requestor;
3632 if (!device->browse)
3633 return btd_error_does_not_exist(msg);
3635 if (!dbus_message_is_method_call(device->browse->msg, DEVICE_INTERFACE,
3636 "DiscoverServices"))
3637 return btd_error_not_authorized(msg);
3639 requestor = browse_request_get_requestor(device->browse);
3641 /* only the discover requestor can cancel the inquiry process */
3642 if (!requestor || !g_str_equal(requestor, sender))
3643 return btd_error_not_authorized(msg);
3645 discover_services_reply(device->browse, -ECANCELED, NULL);
3648 browse_request_cancel(device->browse);
3650 return dbus_message_new_method_return(msg);
3653 void device_set_gatt_connected(struct btd_device *device, gboolean connected)
3655 if (device == NULL) {
3656 error("device is NULL");
3660 if (device->gatt_connected == connected) {
3661 error("same state change for gatt_connected : %d", connected);
3664 DBG("GattConnected %d", connected);
3666 device->gatt_connected = connected;
3667 g_dbus_emit_property_changed(dbus_conn, device->path,
3668 DEVICE_INTERFACE, "GattConnected");
3671 static DBusMessage *connect_le(DBusConnection *conn, DBusMessage *msg,
3674 struct btd_device *dev = user_data;
3675 dbus_bool_t auto_connect = FALSE;
3680 * If a LE connection is requested without device discovery,
3681 * we try to get device object. Here, technology can be updated
3682 * if there is matched device object. Or, a new device object
3685 dev = btd_adapter_get_device(dev->adapter, &dev->bdaddr,
3688 error("Unable to get device object");
3689 return btd_error_not_supported(msg);
3693 if (dev->le_state.connected)
3694 return dbus_message_new_method_return(msg);
3696 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &auto_connect,
3698 return btd_error_invalid_args(msg);
3700 btd_device_set_temporary(dev, false);
3703 DBG("Start BLE auto connection");
3704 dev->disable_auto_connect = FALSE;
3705 device_set_auto_connect(dev, TRUE);
3707 return dbus_message_new_method_return(msg);
3710 err = device_connect_le(dev);
3712 return btd_error_failed(msg, strerror(-err));
3714 dev->connect = dbus_message_ref(msg);
3719 static DBusMessage *disconnect_le(DBusConnection *conn, DBusMessage *msg,
3722 struct btd_device *dev = user_data;
3725 return btd_error_not_supported(msg);
3728 * Disable connections through passive sccanning
3730 if (dev->auto_connect) {
3731 DBG("Stop BLE auto connection");
3732 dev->disable_auto_connect = FALSE;
3733 device_set_auto_connect(dev, FALSE);
3735 if (!dev->le_state.connected) {
3736 g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
3741 device_request_disconnect(dev, msg);
3746 static DBusMessage *connect_ipsp(DBusConnection *conn, DBusMessage *msg,
3749 struct btd_device *device = user_data;
3751 DBG("bdaddr_type %d", device->bdaddr_type);
3753 if (device->bdaddr_type == BDADDR_BREDR) {
3755 device->bdaddr_type = BDADDR_LE_PUBLIC;
3757 device = btd_adapter_get_device(device->adapter,
3758 &device->bdaddr, BDADDR_LE_PUBLIC);
3760 return btd_error_no_such_adapter(msg);
3764 if (device->ipsp_connected)
3765 return btd_error_already_connected(msg);
3767 /* Initiate Connection for 6Lowan*/
3768 if (btd_adapter_connect_ipsp(device->adapter, &device->bdaddr,
3769 device->bdaddr_type) != 0)
3770 return btd_error_failed(msg, "ConnectFailed");
3772 return dbus_message_new_method_return(msg);;
3775 static DBusMessage *disconnect_ipsp(DBusConnection *conn, DBusMessage *msg,
3778 struct btd_device *device = user_data;
3779 DBG("bdaddr_type %d", device->bdaddr_type);
3781 if (device->bdaddr_type == BDADDR_BREDR)
3782 return btd_error_not_supported(msg);
3784 if (!device->ipsp_connected)
3785 return btd_error_not_connected(msg);
3787 /* Disconnect the 6Lowpan connection */
3788 if (btd_adapter_disconnect_ipsp(device->adapter, &device->bdaddr,
3789 device->bdaddr_type) != 0)
3790 return btd_error_failed(msg, "DisconnectFailed");
3792 /* TODO: Handle disconnection of GATT connection, If the connection
3793 * is established as part of IPSP connection. */
3795 return dbus_message_new_method_return(msg);;
3798 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3799 static GSList *find_otc_conn_info(GSList *list, const char *path)
3803 for (l = list; l != NULL; l = g_slist_next(l)) {
3804 struct otc_conn_info *info = l->data;
3806 if (g_strcmp0(info->dev_path, path) == 0)
3813 static gboolean otc_disconnected_cb(GIOChannel *chan, GIOCondition cond,
3816 struct otc_conn_info *conn_info;
3817 const char *dev_path = (const char *) user_data;
3820 DBG("OTC Disconnected");
3822 l = find_otc_conn_info(otc_connection_list, dev_path);
3826 conn_info = l->data;
3827 conn_info->otc_connected = false;
3829 g_dbus_emit_signal(dbus_conn, dev_path,
3830 DEVICE_INTERFACE, "OtcDisconnected",
3833 if (conn_info->io) {
3834 g_io_channel_shutdown(conn_info->io, TRUE, NULL);
3835 g_io_channel_unref(conn_info->io);
3838 otc_connection_list = g_slist_remove(otc_connection_list, conn_info);
3844 static void otc_connect_cb(GIOChannel *chan, GError *gerr,
3847 const char *dev_path;
3849 struct otc_conn_info *conn_info = NULL;
3850 DBusMessage *msg = NULL;
3851 DBusMessageIter iter;
3857 dev_path = (const char *) user_data;
3858 l = find_otc_conn_info(otc_connection_list, dev_path);
3863 conn_info = l->data;
3864 conn_info->otc_connected = true;
3866 fd = g_io_channel_unix_get_fd(chan);
3868 DBG("OTC Connected fd [%d], role [%s]",
3869 fd, conn_info->role ? "server" : "client");
3870 DBG("dev_path [%s]", dev_path);
3872 g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
3873 otc_disconnected_cb, (gpointer) dev_path);
3875 if (conn_info->role == BT_OTP_CLIENT_ROLE) {
3876 msg = dbus_message_new_method_call(BT_OTC_SERVICE_NAME,
3878 BT_OTC_INTERFACE_NAME,
3880 } else if (conn_info->role == BT_OTP_SERVER_ROLE) {
3881 msg = dbus_message_new_method_call(BT_OTS_SERVICE_NAME,
3883 BT_OTS_INTERFACE_NAME,
3888 error("Unable to create NewConnection call");
3892 dbus_message_iter_init_append(msg, &iter);
3894 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &dev_path);
3896 dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd);
3898 if (!g_dbus_send_message(dbus_conn, msg)) {
3899 error("sending NewConnection failed");
3900 dbus_message_unref(msg);
3904 int btd_adapter_connect_otc(struct btd_device *device)
3906 struct btd_adapter *adapter = device_get_adapter(device);
3907 const bdaddr_t *src = btd_adapter_get_address(adapter);
3908 uint8_t src_type = btd_adapter_get_le_address_type(adapter);
3909 const bdaddr_t *dest = device_get_address(device);
3910 uint8_t dest_type = device->bdaddr_type;
3911 struct otc_conn_info *conn_info = NULL;
3912 const char *dev_path = device_get_path(device);
3913 GError *gerr = NULL;
3915 conn_info = g_malloc0(sizeof(struct otc_conn_info));
3917 conn_info->io = bt_io_connect(otc_connect_cb,
3918 (gpointer) dev_path, NULL, &gerr,
3919 BT_IO_OPT_SOURCE_BDADDR, src,
3920 BT_IO_OPT_SOURCE_TYPE, src_type,
3921 BT_IO_OPT_DEST_BDADDR, dest,
3922 BT_IO_OPT_DEST_TYPE, dest_type,
3923 BT_IO_OPT_PSM, OTP_PSM,
3924 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
3927 if (!conn_info->io) {
3928 error("OTC Connect failed : %s", gerr->message);
3934 conn_info->dev_path = dev_path;
3935 conn_info->role = BT_OTP_CLIENT_ROLE;
3936 conn_info->otc_connected = false;
3937 g_io_channel_set_close_on_unref(conn_info->io, FALSE);
3939 otc_connection_list = g_slist_append(otc_connection_list, conn_info);
3943 static DBusMessage *connect_otc(DBusConnection *conn, DBusMessage *msg,
3946 struct btd_device *device = user_data;
3950 return btd_error_invalid_args(msg);
3952 l = find_otc_conn_info(otc_connection_list, device_get_path(device));
3955 struct otc_conn_info *info = l->data;
3956 if (info->otc_connected)
3957 return btd_error_already_connected(msg);
3959 return btd_error_busy(msg);
3962 if (btd_adapter_connect_otc(device) != 0)
3963 return btd_error_failed(msg, "ConnectFailed");
3965 return dbus_message_new_method_return(msg);
3968 static DBusMessage *disconnect_otc(DBusConnection *conn, DBusMessage *msg,
3971 struct btd_device *device = user_data;
3972 struct otc_conn_info *info = NULL;
3976 l = find_otc_conn_info(otc_connection_list, device_get_path(device));
3979 return btd_error_does_not_exist(msg);
3983 if (!info->otc_connected)
3984 return btd_error_not_connected(msg);
3986 sock = g_io_channel_unix_get_fd(info->io);
3988 shutdown(sock, SHUT_RDWR);
3990 g_io_channel_shutdown(info->io, FALSE, NULL);
3992 g_io_channel_unref(info->io);
3995 return dbus_message_new_method_return(msg);
3998 int btd_adapter_listen_otc(struct btd_device *device)
4000 struct btd_adapter *adapter = device_get_adapter(device);
4001 const bdaddr_t *src = btd_adapter_get_address(adapter);
4002 uint8_t type = btd_adapter_get_le_address_type(adapter);
4003 struct otc_conn_info *conn_info = NULL;
4004 const char *dev_path = device_get_path(device);
4005 GError *gerr = NULL;
4007 conn_info = g_malloc0(sizeof(struct otc_conn_info));
4009 conn_info->io = bt_io_listen(otc_connect_cb, NULL, (gpointer) dev_path,
4011 BT_IO_OPT_SOURCE_BDADDR, src,
4012 BT_IO_OPT_SOURCE_TYPE, type,
4013 BT_IO_OPT_PSM, OTP_PSM,
4014 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
4017 if (!conn_info->io) {
4018 error("OTC Listen failed : %s", gerr->message);
4024 conn_info->dev_path = dev_path;
4025 conn_info->otc_connected = false;
4026 conn_info->role = BT_OTP_SERVER_ROLE;
4027 g_io_channel_set_close_on_unref(conn_info->io, FALSE);
4029 otc_connection_list = g_slist_append(otc_connection_list, conn_info);
4033 static DBusMessage *listen_otc(DBusConnection *conn, DBusMessage *msg,
4036 struct btd_device *device = user_data;
4040 return btd_error_invalid_args(msg);
4042 l = find_otc_conn_info(otc_connection_list, device_get_path(device));
4045 struct otc_conn_info *info = l->data;
4046 if (info->otc_connected)
4047 return btd_error_already_connected(msg);
4049 return btd_error_busy(msg);
4052 if (btd_adapter_listen_otc(device) != 0)
4053 return btd_error_failed(msg, "ListenFailed");
4055 return dbus_message_new_method_return(msg);
4059 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4060 /********************* L2CAP LE SOCKET IMPLEMENTATION *************************/
4061 static GSList *find_l2cap_le_profile_info(GSList *list, const char *owner,
4065 for (l = list; l != NULL; l = g_slist_next(l)) {
4066 struct l2cap_le_profile_info *info = l->data;
4071 if (g_strcmp0(info->owner, owner))
4074 if (!g_strcmp0(info->path, path))
4081 static int parse_l2cap_le_opt(struct l2cap_le_profile_info *info,
4082 const char *key, DBusMessageIter *value)
4084 int type = dbus_message_iter_get_arg_type(value);
4087 if (strcasecmp(key, "RequireAuthentication") == 0) {
4088 if (type != DBUS_TYPE_BOOLEAN)
4091 dbus_message_iter_get_basic(value, &b);
4094 info->sec_level = BT_IO_SEC_MEDIUM;
4096 info->sec_level = BT_IO_SEC_LOW;
4097 } else if (strcasecmp(key, "RequireAuthorization") == 0) {
4098 if (type != DBUS_TYPE_BOOLEAN)
4100 dbus_message_iter_get_basic(value, &b);
4101 info->authorize = b;
4107 static struct l2cap_le_profile_info *create_l2cap_le_socket(const char *owner,
4108 const char *path, int psm, DBusMessageIter *opts)
4110 struct l2cap_le_profile_info *info = NULL;
4112 if (psm < 0 || psm > BTD_L2CAP_LE_PSM_MAX)
4115 info = g_malloc0(sizeof(struct l2cap_le_profile_info));
4117 info->owner = g_strdup(owner);
4118 info->path = g_strdup(path);
4121 while (dbus_message_iter_get_arg_type(opts) == DBUS_TYPE_DICT_ENTRY) {
4122 DBusMessageIter value, entry;
4125 dbus_message_iter_recurse(opts, &entry);
4126 dbus_message_iter_get_basic(&entry, &key);
4128 dbus_message_iter_next(&entry);
4129 dbus_message_iter_recurse(&entry, &value);
4131 if (parse_l2cap_le_opt(info, key, &value) < 0)
4132 error("Invalid value for l2cap_le_socket option %s", key);
4134 dbus_message_iter_next(opts);
4138 info->name = g_strdup_printf("%s%s/%d", owner, path, psm);
4143 static void l2cap_le_io_destroy(gpointer p)
4145 struct l2cap_le_conn_info *conn = p;
4147 if (conn->io_id > 0)
4148 g_source_remove(conn->io_id);
4151 g_io_channel_shutdown(conn->io, FALSE, NULL);
4152 g_io_channel_unref(conn->io);
4155 if (conn->auth_id != 0)
4156 btd_cancel_authorization(conn->auth_id);
4158 if (conn->auth_uuid)
4159 free(conn->auth_uuid);
4164 static gboolean l2cap_le_disconnected_cb(GIOChannel *chan,
4165 GIOCondition cond, gpointer user_data)
4167 struct l2cap_le_conn_info *conn = user_data;
4168 struct l2cap_le_profile_info *info = conn->profile_info;
4170 DBG(" L2CAP LE socket disconnected role [%s] ",
4171 info->role == BT_L2CAP_LE_SERVER_ROLE ? "server" : "client");
4173 g_dbus_emit_signal(dbus_conn, conn->dev_path,
4174 DEVICE_INTERFACE, "L2CAPLEDisconnected",
4177 conn->connected = false;
4179 info->conn = g_slist_remove(info->conn, conn);
4180 l2cap_le_io_destroy(conn);
4184 static void l2cap_le_connect_cb(GIOChannel *chan, GError *gerr,
4187 struct l2cap_le_conn_info *conn = (struct l2cap_le_conn_info *) user_data;
4188 struct l2cap_le_profile_info *info = conn->profile_info;
4189 DBusMessage *msg = NULL;
4190 DBusMessageIter iter;
4191 const char *dev_path;
4193 GError *io_err = NULL;
4196 if (!bt_io_get(chan, &io_err,
4197 BT_IO_OPT_DEST, addr,
4198 BT_IO_OPT_INVALID)) {
4200 error("%s failed %s", info->name, gerr->message);
4201 g_error_free(io_err);
4204 error("Unable to get connect data for %s: %s",
4205 info->name, io_err->message);
4212 error("%s failed to connect to %s: %s", info->name, addr,
4217 conn->connected = true;
4219 fd = g_io_channel_unix_get_fd(chan);
4221 if (conn->io_id == 0)
4222 conn->io_id = g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
4223 l2cap_le_disconnected_cb, conn);
4225 msg = dbus_message_new_method_call(info->owner,
4227 BT_L2CAP_LE_INTERFACE_NAME,
4231 error("Unable to create NewConnection call");
4235 dev_path = conn->dev_path;
4237 dbus_message_iter_init_append(msg, &iter);
4239 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &dev_path);
4241 dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd);
4243 if (!g_dbus_send_message(dbus_conn, msg)) {
4244 error("sending NewConnection failed");
4245 dbus_message_unref(msg);
4249 DBG("L2CAP_LE Connected fd [%d] addr [%s], role [%s]",fd, addr,
4250 info->role == BT_L2CAP_LE_SERVER_ROLE ? "server" : "client");
4255 g_error_free(io_err);
4257 info->conn = g_slist_remove(info->conn, conn);
4258 l2cap_le_io_destroy(conn);
4261 static struct l2cap_le_conn_info *create_l2cap_le_conn(
4262 struct l2cap_le_conn_info *server, GIOChannel *io,
4263 bdaddr_t *src, bdaddr_t *dst, uint8_t dst_type)
4265 struct l2cap_le_conn_info *conn;
4267 struct btd_device *device;
4268 struct btd_adapter *adapter = adapter_find(src);
4271 error("could not find adapter");
4275 device = btd_adapter_get_device(adapter, dst, dst_type);
4277 error("could not find Device");
4281 conn = g_new0(struct l2cap_le_conn_info, 1);
4282 conn->io = g_io_channel_ref(io);
4283 conn->profile_info = server->profile_info;
4284 conn->dev_path = device_get_path(device);
4286 cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL;
4287 conn->io_id = g_io_add_watch(io, cond, l2cap_le_disconnected_cb, conn);
4292 static void l2cap_le_auth(DBusError *err, void *user_data)
4294 struct l2cap_le_conn_info *conn = user_data;
4295 struct l2cap_le_profile_info *info = conn->profile_info;
4296 GError *gerr = NULL;
4301 bt_io_get(conn->io, &gerr, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID);
4303 error("Unable to get connect data for %s: %s",
4304 info->name, gerr->message);
4309 if (err && dbus_error_is_set(err)) {
4310 error("%s rejected %s: %s", info->name, addr, err->message);
4314 if (!bt_io_accept(conn->io, l2cap_le_connect_cb, conn, NULL, &gerr)) {
4315 error("bt_io_accept: %s", gerr->message);
4320 DBG("%s authorized to connect to %s", addr, info->name);
4324 info->conn = g_slist_remove(info->conn, conn);
4325 l2cap_le_io_destroy(conn);
4328 static void l2cap_le_confirm(GIOChannel *io, gpointer user_data)
4330 struct l2cap_le_conn_info *server = user_data;
4331 struct l2cap_le_profile_info *info = server->profile_info;
4332 struct l2cap_le_conn_info *conn;
4333 GError *gerr = NULL;
4337 char *uuid = g_malloc0(UUID_LEN * sizeof(char));
4339 bt_io_get(io, &gerr,
4340 BT_IO_OPT_SOURCE_BDADDR, &src,
4341 BT_IO_OPT_DEST_BDADDR, &dst,
4342 BT_IO_OPT_DEST_TYPE, &dst_type,
4343 BT_IO_OPT_DEST, addr,
4346 error("%s failed to get connect data: %s", info->name,
4352 DBG("incoming connect from %s for authorization", addr);
4354 conn = create_l2cap_le_conn(server, io, &src, &dst, dst_type);
4358 /* Use custom uuid of the form "FFFFFFFF-FFFF-FFFF-FFFF-<psm in 12 digits>"
4359 * for authorizing l2cap_le socket using existing flow.
4360 * This custom uuid will be used in the BT-OAL layer to identify the
4361 * l2cap_le socket authorization and extracting psm from it.
4363 snprintf(uuid, UUID_LEN, "%s%012d", L2CAP_LE_UUID_SUBSTR, server->psm);
4364 conn->auth_uuid = uuid;
4366 conn->auth_id = btd_request_authorization(&src, &dst,
4367 (const char *)conn->auth_uuid, l2cap_le_auth, conn);
4368 if (conn->auth_id == 0) {
4369 error("%s authorization failure", info->name);
4370 l2cap_le_io_destroy(conn);
4374 info->conn = g_slist_append(info->conn, conn);
4376 DBG("%s authorizing connection from %s", info->name, addr);
4379 static void l2cap_le_direct_connect(GIOChannel *io, GError *err,
4382 struct l2cap_le_conn_info *server = user_data;
4383 struct l2cap_le_profile_info *info = server->profile_info;
4384 struct l2cap_le_conn_info *conn;
4385 GError *gerr = NULL;
4389 bt_io_get(io, &gerr,
4390 BT_IO_OPT_SOURCE_BDADDR, &src,
4391 BT_IO_OPT_DEST_BDADDR, &dst,
4392 BT_IO_OPT_DEST_TYPE, &dst_type,
4395 error("%s failed to get connect data: %s", info->name,
4401 conn = create_l2cap_le_conn(server, io, &src, &dst, dst_type);
4405 info->conn = g_slist_append(info->conn, conn);
4407 l2cap_le_connect_cb(io, err, conn);
4410 static void _remove_l2cap_le_socket(struct l2cap_le_profile_info *info)
4412 l2cap_le_socket_list = g_slist_remove(l2cap_le_socket_list, info);
4414 DBG("Removed \"%s\"", info->name);
4417 l2cap_le_io_destroy((gpointer)info->server);
4418 g_slist_free_full(info->conn, l2cap_le_io_destroy);
4421 g_free(info->owner);
4427 static void l2cap_le_socket_exited(DBusConnection *conn, void *user_data)
4429 struct l2cap_le_profile_info *info = user_data;
4431 DBG("l2cap le server \"%s\" exited", info->name);
4433 _remove_l2cap_le_socket(info);
4436 static int _connect_l2cap_le(struct btd_device *device,
4437 struct l2cap_le_profile_info *info)
4439 struct btd_adapter *adapter = device_get_adapter(device);
4440 const bdaddr_t *src = btd_adapter_get_address(adapter);
4441 uint8_t src_type = btd_adapter_get_le_address_type(adapter);
4442 const bdaddr_t *dest = device_get_address(device);
4443 uint8_t dest_type = device->bdaddr_type;
4444 const char *dev_path = device_get_path(device);
4445 GError *gerr = NULL;
4446 struct l2cap_le_conn_info *conn = NULL;
4448 conn = g_malloc0(sizeof(struct l2cap_le_conn_info));
4449 info->conn = g_slist_append(info->conn, conn);
4451 conn->io = bt_io_connect(l2cap_le_connect_cb,
4453 BT_IO_OPT_SOURCE_BDADDR, src,
4454 BT_IO_OPT_SOURCE_TYPE, src_type,
4455 BT_IO_OPT_DEST_BDADDR, dest,
4456 BT_IO_OPT_DEST_TYPE, dest_type,
4457 BT_IO_OPT_PSM, info->psm,
4458 BT_IO_OPT_SEC_LEVEL, info->sec_level,
4462 error("L2CAP_LE Connect failed : %s", gerr->message);
4464 _remove_l2cap_le_socket(info);
4468 info->role = BT_L2CAP_LE_CLIENT_ROLE;
4469 conn->dev_path = dev_path;
4470 conn->profile_info = info;
4471 conn->connected = false;
4472 g_io_channel_set_close_on_unref(conn->io, FALSE);
4474 l2cap_le_socket_list = g_slist_append(l2cap_le_socket_list, info);
4478 static int _listen_l2cap_le(struct btd_adapter *adapter,
4479 struct l2cap_le_profile_info *info)
4481 const bdaddr_t *src = btd_adapter_get_address(adapter);
4482 uint8_t type = btd_adapter_get_le_address_type(adapter);
4483 GError *gerr = NULL;
4484 struct l2cap_le_conn_info *conn = NULL;
4485 BtIOConfirm confirm;
4486 BtIOConnect connect;
4489 if (info->authorize) {
4490 confirm = l2cap_le_confirm;
4494 connect = l2cap_le_direct_connect;
4497 conn = g_malloc0(sizeof(struct l2cap_le_conn_info));
4498 info->server = conn;
4500 conn->io = bt_io_listen(connect, confirm, (gpointer)conn,
4502 BT_IO_OPT_SOURCE_BDADDR, src,
4503 BT_IO_OPT_SOURCE_TYPE, type,
4504 BT_IO_OPT_PSM, info->psm,
4505 BT_IO_OPT_SEC_LEVEL, info->sec_level,
4509 error("L2cap_LE Listen failed : %s", gerr->message);
4511 _remove_l2cap_le_socket(info);
4515 bt_io_get(conn->io, &gerr, BT_IO_OPT_PSM, &psm, BT_IO_OPT_INVALID);
4517 DBG("L2CAP LE Socket listen to PSM %d successful", psm);
4519 conn->connected = false;
4520 info->role = BT_L2CAP_LE_SERVER_ROLE;
4522 conn->profile_info = info;
4523 g_io_channel_set_close_on_unref(conn->io, FALSE);
4525 l2cap_le_socket_list = g_slist_append(l2cap_le_socket_list, info);
4530 static DBusMessage *connect_l2cap_le_socket(DBusConnection *conn,
4531 DBusMessage *msg, void *user_data)
4533 struct btd_device *device = user_data;
4535 const char *path, *sender;
4537 DBusMessageIter args, opts;
4538 struct l2cap_le_profile_info *info = NULL;
4541 return btd_error_invalid_args(msg);
4543 sender = dbus_message_get_sender(msg);
4545 dbus_message_iter_init(msg, &args);
4546 dbus_message_iter_get_basic(&args, &path);
4547 dbus_message_iter_next(&args);
4549 dbus_message_iter_get_basic(&args, &psm);
4550 dbus_message_iter_next(&args);
4552 l = find_l2cap_le_profile_info(l2cap_le_socket_list, sender, path);
4555 struct l2cap_le_profile_info *info = l->data;
4557 struct l2cap_le_conn_info *conn_info = info->conn->data;
4558 if (conn_info && conn_info->connected)
4559 return btd_error_already_connected(msg);
4561 return btd_error_busy(msg);
4563 error("Something is wrong!!!");
4564 return btd_error_failed(msg, "ConnectFailed due to some internal error");
4568 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
4569 return btd_error_invalid_args(msg);
4571 dbus_message_iter_recurse(&args, &opts);
4573 info = create_l2cap_le_socket(sender, path, psm, &opts);
4575 return btd_error_invalid_args(msg);
4577 info->role = BT_L2CAP_LE_CLIENT_ROLE;
4579 DBG("connect l2cap l2 socket channel %d", (int)psm);
4581 if (_connect_l2cap_le(device, info) != 0)
4582 return btd_error_failed(msg, "ConnectFailed");
4584 info->id = g_dbus_add_disconnect_watch(conn, sender, l2cap_le_socket_exited,
4587 return dbus_message_new_method_return(msg);
4590 DBusMessage *listen_l2cap_le_socket(DBusConnection *conn, DBusMessage *msg,
4593 struct btd_adapter *adapter = user_data;
4595 const char *path, *sender;
4597 DBusMessageIter args, opts;
4598 struct l2cap_le_profile_info *info = NULL;
4600 sender = dbus_message_get_sender(msg);
4602 dbus_message_iter_init(msg, &args);
4603 dbus_message_iter_get_basic(&args, &path);
4604 dbus_message_iter_next(&args);
4606 dbus_message_iter_get_basic(&args, &psm);
4607 dbus_message_iter_next(&args);
4609 l = find_l2cap_le_profile_info(l2cap_le_socket_list, sender, path);
4612 return btd_error_already_exists(msg);
4614 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
4615 return btd_error_invalid_args(msg);
4617 dbus_message_iter_recurse(&args, &opts);
4619 info = create_l2cap_le_socket(sender, path, psm, &opts);
4621 return btd_error_invalid_args(msg);
4623 info->role = BT_L2CAP_LE_SERVER_ROLE;
4625 DBG("listen l2cap_le socket to psm %d", (int)psm);
4627 if (_listen_l2cap_le(adapter, info) != 0)
4628 return btd_error_failed(msg, "ListenFailed");
4630 info->id = g_dbus_add_disconnect_watch(conn, sender, l2cap_le_socket_exited,
4633 return dbus_message_new_method_return(msg);
4636 DBusMessage *get_psm_l2cap_le(DBusConnection *conn, DBusMessage *msg)
4638 const char *path, *sender;
4642 DBusMessageIter args;
4643 struct l2cap_le_profile_info *info;
4645 sender = dbus_message_get_sender(msg);
4647 DBG("sender %s", sender);
4649 dbus_message_iter_init(msg, &args);
4651 dbus_message_iter_get_basic(&args, &path);
4652 dbus_message_iter_next(&args);
4654 l = find_l2cap_le_profile_info(l2cap_le_socket_list, sender, path);
4657 DBG("L2cap LE socket not exist");
4658 return btd_error_does_not_exist(msg);
4664 psm = info->server->psm;
4666 return btd_error_does_not_exist(msg);
4668 reply = dbus_message_new_method_return(msg);
4670 return btd_error_failed(msg,
4671 "Failed to create reply.");
4673 dbus_message_append_args(reply,
4674 DBUS_TYPE_UINT32, &psm,
4680 DBusMessage *remove_l2cap_le_socket(DBusConnection *conn, DBusMessage *msg)
4682 const char *path, *sender;
4683 struct l2cap_le_profile_info *info = NULL;
4686 sender = dbus_message_get_sender(msg);
4688 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
4690 return btd_error_invalid_args(msg);
4692 DBG("remove socket sender %s path %s", sender, path);
4694 l = find_l2cap_le_profile_info(l2cap_le_socket_list, sender, path);
4697 DBG("L2cap LE socket not exist");
4698 return btd_error_does_not_exist(msg);
4703 g_dbus_remove_watch(conn, info->id);
4704 _remove_l2cap_le_socket(info);
4706 return dbus_message_new_method_return(msg);
4710 static DBusMessage *le_set_data_length(
4711 DBusConnection *conn, DBusMessage *msg,
4714 dbus_uint16_t max_tx_octets;
4715 dbus_uint16_t max_tx_time;
4716 struct btd_device *device = user_data;
4720 if (!dbus_message_get_args(msg, NULL,
4721 DBUS_TYPE_UINT16, &max_tx_octets,
4722 DBUS_TYPE_UINT16, &max_tx_time,
4723 DBUS_TYPE_INVALID)) {
4724 DBG("error in retrieving values");
4725 return btd_error_invalid_args(msg);
4728 if (device->bdaddr_type == BDADDR_BREDR)
4729 return btd_error_not_supported(msg);
4731 ba2str(&device->bdaddr, addr);
4733 DBG("Remote device address: %s", addr);
4734 DBG("Max tx octets: %u, Max tx time: %u",
4735 max_tx_octets, max_tx_time);
4737 status = btd_adapter_le_set_data_length(device->adapter,
4738 &device->bdaddr, max_tx_octets,
4742 return btd_error_failed(msg, "Unable to set le data length values");
4744 return dbus_message_new_method_return(msg);
4747 static DBusMessage *set_trusted_profile(DBusConnection *conn,
4748 DBusMessage *msg, void *data)
4750 struct btd_device *dev = data;
4751 dbus_bool_t profile_trusted;
4752 const char *pattern;
4754 uint32_t pbap = dev->trusted_profiles.pbap;
4755 uint32_t map = dev->trusted_profiles.map;
4756 uint32_t sap = dev->trusted_profiles.sap;
4757 uint32_t hfp_hs = dev->trusted_profiles.hfp_hs;
4758 uint32_t a2dp = dev->trusted_profiles.a2dp;
4760 if (!dbus_message_get_args(msg, NULL,
4761 DBUS_TYPE_STRING, &pattern,
4762 DBUS_TYPE_BOOLEAN, &profile_trusted,
4764 return btd_error_invalid_args(msg);
4766 DBG("Pattern : %s", pattern);
4767 uuid = bt_name2string(pattern);
4768 DBG("UUID : %s", uuid);
4769 DBG("profile Trusted : %d %d %d", dev->trusted_profiles.pbap,
4770 dev->trusted_profiles.map, dev->trusted_profiles.sap);
4771 DBG("profile Restricted : %d %d", dev->trusted_profiles.hfp_hs,
4772 dev->trusted_profiles.a2dp);
4773 if (g_strcmp0(uuid, OBEX_PBAP_UUID) == 0) {
4774 if (profile_trusted)
4775 pbap = SUPPORTED_TRUSTED;
4777 pbap = SUPPORTED_BLOCKED;
4778 } else if (g_strcmp0(uuid, OBEX_MAP_UUID) == 0) {
4779 if (profile_trusted)
4780 map = SUPPORTED_TRUSTED;
4782 map = SUPPORTED_BLOCKED;
4783 } else if (g_strcmp0(uuid, SAP_UUID) == 0) {
4784 if (profile_trusted)
4785 sap = SUPPORTED_TRUSTED;
4787 sap = SUPPORTED_BLOCKED;
4788 } else if (g_strcmp0(uuid, HFP_HS_UUID) == 0) {
4789 if (profile_trusted)
4790 hfp_hs = SUPPORTED_TRUSTED;
4792 hfp_hs = SUPPORTED_BLOCKED;
4793 } else if (g_strcmp0(uuid, A2DP_SINK_UUID) == 0) {
4794 if (profile_trusted)
4795 a2dp = SUPPORTED_TRUSTED;
4797 a2dp = SUPPORTED_BLOCKED;
4800 return btd_error_invalid_args(msg);
4804 btd_device_set_trusted_profiles(dev, pbap, map, sap, hfp_hs, a2dp);
4805 return dbus_message_new_method_return(msg);
4808 static DBusMessage *is_connected_profile(DBusConnection *conn, DBusMessage *msg,
4811 struct btd_device *dev = user_data;
4812 struct btd_service *service;
4813 btd_service_state_t state;
4814 const char *pattern;
4819 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
4821 return btd_error_invalid_args(msg);
4823 reply = dbus_message_new_method_return(msg);
4825 return btd_error_invalid_args(reply);
4827 uuid = bt_name2string(pattern);
4828 DBG("is_connected_profile_uuid : %s", uuid);
4829 service = btd_device_get_service(dev, uuid);
4831 if ((service == NULL) && (g_strcmp0(uuid, HFP_HS_UUID) == 0)) {
4832 DBG("HFP service is not found check for HSP service");
4833 service = btd_device_get_service(dev, HSP_HS_UUID);
4839 return btd_error_not_connected(msg);
4841 state = btd_service_get_state(service);
4842 DBG("Connected State : %d", state);
4844 if (state == BTD_SERVICE_STATE_CONNECTED)
4849 dbus_message_append_args(reply,
4850 DBUS_TYPE_BOOLEAN, &val,
4856 static DBusMessage *update_le_conn_parm(DBusConnection *conn, DBusMessage *msg,
4859 struct btd_device *device = user_data;
4862 struct le_conn_param param = {0, 0, 0, 0};
4863 uint32_t min, max, latency, to_multiplier;
4867 if (device == NULL) {
4868 error("device is NULL");
4869 return btd_error_invalid_args(msg);
4873 error("le is not supported");
4874 return btd_error_not_supported(msg);
4877 if (!device->gatt_connected || !device->attrib)
4878 return btd_error_not_connected(msg);
4880 io = g_attrib_get_channel(device->attrib);
4882 return btd_error_not_connected(msg);
4884 fd = g_io_channel_unix_get_fd(io);
4886 return btd_error_not_connected(msg);
4888 if (device_get_conn_update_state(device))
4889 return btd_error_in_progress(msg);
4891 device_set_conn_update_state(device, true);
4893 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &min,
4894 DBUS_TYPE_UINT32, &max,
4895 DBUS_TYPE_UINT32, &latency,
4896 DBUS_TYPE_UINT32, &to_multiplier,
4897 DBUS_TYPE_INVALID)) {
4898 error("Invalid args");
4899 return btd_error_invalid_args(msg);
4902 if (min > UINT16_MAX || max > UINT16_MAX ||
4903 latency > UINT16_MAX || to_multiplier > UINT16_MAX) {
4904 error("Invalid args");
4905 return btd_error_invalid_args(msg);
4907 param.min = (uint16_t)min;
4908 param.max = (uint16_t)max;
4909 param.latency = (uint16_t)latency;
4910 param.to_multiplier = (uint16_t)to_multiplier;
4912 if (setsockopt(fd, SOL_BLUETOOTH, BT_LE_CONN_PARAM,
4913 ¶m, sizeof(param)) < 0) {
4914 error("Can't Update LE conn param : %s (%d)",
4915 strerror(errno), errno);
4916 return btd_error_failed(msg, strerror(errno));
4919 return dbus_message_new_method_return(msg);
4922 static void device_request_att_mtu_reponse_cb(bool success, uint8_t att_ecode,
4925 struct btd_device *device = user_data;
4927 DBusMessageIter iter;
4930 if (!device->req_att_mtu)
4933 mtu = bt_gatt_client_get_mtu(device->client);
4937 err_if = ERROR_INTERFACE ".Failed";
4939 reply = dbus_message_new_error(device->req_att_mtu, err_if,
4940 "Request Att MTU failed");
4941 g_dbus_send_message(dbus_conn, reply);
4945 DBG("MTU exchange complete, with MTU: %u", mtu);
4947 reply = dbus_message_new_method_return(device->req_att_mtu);
4951 dbus_message_iter_init_append(reply, &iter);
4953 dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
4955 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
4957 g_dbus_send_message(dbus_conn, reply);
4959 dbus_message_unref(device->req_att_mtu);
4960 device->req_att_mtu = NULL;
4963 static DBusMessage *request_att_mtu(DBusConnection *conn, DBusMessage *msg,
4966 struct btd_device *device = user_data;
4971 if (device == NULL) {
4972 error("device is NULL");
4973 return btd_error_invalid_args(msg);
4977 error("le is not supported");
4978 return btd_error_not_supported(msg);
4981 if (!device->gatt_connected || !device->attrib)
4982 return btd_error_not_connected(msg);
4984 if (!dbus_message_get_args(msg, NULL,
4985 DBUS_TYPE_UINT16, &mtu,
4986 DBUS_TYPE_INVALID)) {
4987 error("Invalid args");
4988 return btd_error_invalid_args(msg);
4993 if (!bt_gatt_request_att_mtu(device->client, mtu,
4994 device_request_att_mtu_reponse_cb, device))
4995 return btd_error_failed(msg, "Unable to Request MTU");
4997 device->req_att_mtu = dbus_message_ref(msg);
5001 static DBusMessage *device_get_ida(DBusConnection *conn, DBusMessage *msg,
5004 struct btd_device *device = user_data;
5005 char device_idaddr[18] = { 0 };
5007 const gchar *id_address = device_idaddr;
5012 return btd_error_invalid_args(msg);
5015 error("It doesn't support LE");
5016 return btd_error_not_supported(msg);
5020 // There is the first RPA. So it's paired device.
5022 ba2str(device->rpa, device_idaddr);
5024 ba2str(&device->bdaddr, device_idaddr);
5025 } else if (device->bdaddr_type != BDADDR_LE_RANDOM) {
5026 // device->bdaddr is identity address.
5027 ba2str(&device->bdaddr, device_idaddr);
5028 } else if ((device->bdaddr.b[5] >> 6) == 0x01) {
5029 // RPA but it's not paired
5030 return btd_error_does_not_exist(msg);
5031 } else if ((device->bdaddr.b[5] >> 6) == 0x03) {
5032 // Static Random address
5033 ba2str(&device->bdaddr, device_idaddr);
5036 return btd_error_not_supported(msg);
5039 reply = dbus_message_new_method_return(msg);
5043 dbus_message_append_args(reply, DBUS_TYPE_STRING, &id_address,
5049 void device_set_conn_update_state(struct btd_device *device, bool state)
5054 device->pending_conn_update = state;
5057 bool device_get_conn_update_state(struct btd_device *device)
5059 return device->pending_conn_update;
5063 static const GDBusMethodTable device_methods[] = {
5064 { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, dev_disconnect) },
5065 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, dev_connect) },
5066 { GDBUS_ASYNC_METHOD("ConnectProfile", GDBUS_ARGS({ "UUID", "s" }),
5067 NULL, connect_profile) },
5068 { GDBUS_ASYNC_METHOD("DisconnectProfile", GDBUS_ARGS({ "UUID", "s" }),
5069 NULL, disconnect_profile) },
5070 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5071 { GDBUS_ASYNC_METHOD("DisconnectExtProfile",
5072 GDBUS_ARGS({ "profile", "o" }), NULL,
5073 disconnect_ext_profile) },
5074 { GDBUS_ASYNC_METHOD("Pair", GDBUS_ARGS({ "conn_type", "y" }), NULL,
5077 { GDBUS_ASYNC_METHOD("Pair", NULL, NULL, pair_device) },
5079 { GDBUS_METHOD("CancelPairing", NULL, NULL, cancel_pairing) },
5080 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5081 { GDBUS_ASYNC_METHOD("ConnectLE", GDBUS_ARGS({ "auto_connect", "b"}),
5082 NULL, connect_le) },
5083 { GDBUS_ASYNC_METHOD("DisconnectLE", NULL, NULL, disconnect_le) },
5084 { GDBUS_METHOD("IsConnectedProfile", GDBUS_ARGS({ "UUID", "s" }),
5085 GDBUS_ARGS({ "IsConnected", "b" }),
5086 is_connected_profile)},
5087 { GDBUS_METHOD("LeConnUpdate", GDBUS_ARGS({ "interval_min", "u" },
5088 { "interval_max", "u" }, { "latency", "u" },
5089 { "time_out", "u" }), NULL,
5090 update_le_conn_parm) },
5091 { GDBUS_ASYNC_METHOD("DiscoverServices", GDBUS_ARGS({ "pattern", "s" }),
5092 NULL, discover_services) },
5093 { GDBUS_METHOD("CancelDiscovery", NULL, NULL, cancel_discover) },
5094 { GDBUS_ASYNC_METHOD("ConnectIpsp", NULL, NULL, connect_ipsp) },
5095 { GDBUS_ASYNC_METHOD("DisconnectIpsp", NULL, NULL, disconnect_ipsp) },
5096 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5097 { GDBUS_METHOD("ConnectOtc", NULL, NULL, connect_otc) },
5098 { GDBUS_METHOD("DisconnectOtc", NULL, NULL, disconnect_otc) },
5099 { GDBUS_METHOD("ListenOtc", NULL, NULL, listen_otc) },
5100 { GDBUS_ASYNC_METHOD("ConnectL2capLESocket",
5101 GDBUS_ARGS({ "path", "o"}, { "psm", "i" }, { "options", "a{sv}" }),
5102 NULL, connect_l2cap_le_socket) },
5104 { GDBUS_ASYNC_METHOD("LESetDataLength",
5105 GDBUS_ARGS({"max_tx_octets", "q" },
5106 { "max_tx_time", "q" }), NULL,
5107 le_set_data_length)},
5108 { GDBUS_ASYNC_METHOD("RequestAttMtu", GDBUS_ARGS({ "mtu", "q" }),
5109 GDBUS_ARGS({ "mtu", "q" }, { "status", "y"}),
5111 { GDBUS_METHOD("GetIDAddress", NULL, GDBUS_ARGS({ "IDAdress", "s" }),
5113 { GDBUS_METHOD("SetTrustedProfile",
5114 GDBUS_ARGS({ "uuid", "s"}, { "trusted", "b"}), NULL,
5115 set_trusted_profile) },
5120 static const GDBusPropertyTable device_properties[] = {
5121 { "Address", "s", dev_property_get_address },
5122 { "AddressType", "s", property_get_address_type },
5123 { "Name", "s", dev_property_get_name, NULL, dev_property_exists_name },
5124 { "Alias", "s", dev_property_get_alias, dev_property_set_alias },
5125 { "Class", "u", dev_property_get_class, NULL,
5126 dev_property_exists_class },
5127 { "Appearance", "q", dev_property_get_appearance, NULL,
5128 dev_property_exists_appearance },
5129 { "Icon", "s", dev_property_get_icon, NULL,
5130 dev_property_exists_icon },
5131 { "Paired", "b", dev_property_get_paired },
5132 { "Trusted", "b", dev_property_get_trusted, dev_property_set_trusted },
5133 { "Blocked", "b", dev_property_get_blocked, dev_property_set_blocked },
5134 { "LegacyPairing", "b", dev_property_get_legacy },
5135 { "RSSI", "n", dev_property_get_rssi, NULL, dev_property_exists_rssi },
5136 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5137 {"IsAliasSet", "b", dev_property_get_alias_set },
5138 { "Connected", "y", dev_property_get_connected },
5140 { "Connected", "b", dev_property_get_connected },
5142 { "UUIDs", "as", dev_property_get_uuids },
5143 { "Modalias", "s", dev_property_get_modalias, NULL,
5144 dev_property_exists_modalias },
5145 { "Adapter", "o", dev_property_get_adapter },
5146 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5147 /* To handle Failed Legacy Pairing when initiated from Remote device*/
5148 { "LegacyPaired", "b", dev_property_get_paired },
5149 { "LegacyManufacturerDataLen", "q", property_get_manufacturer_data_len },
5150 { "LegacyManufacturerData", "ay", property_get_manufacturer_data },
5151 { "GattConnected", "b", dev_property_get_gatt_connected },
5152 { "PayloadTimeout", "q", dev_property_get_payload},
5153 { "LastAddrType", "y", dev_property_get_last_addr_type},
5154 { "IpspConnected", "b", dev_property_get_ipsp_conn_state },
5155 { "IpspBtInterfaceInfo", "s", dev_property_get_ipsp_conn_bt_iface_name },
5156 { "AttMtu", "q", dev_property_get_att_mtu },
5157 { "TrustedProfiles", "u", dev_property_get_trusted_profiles},
5159 { "ManufacturerData", "a{qv}", dev_property_get_manufacturer_data,
5160 NULL, dev_property_manufacturer_data_exist },
5161 { "ServiceData", "a{sv}", dev_property_get_service_data,
5162 NULL, dev_property_service_data_exist },
5163 { "TxPower", "n", dev_property_get_tx_power, NULL,
5164 dev_property_exists_tx_power },
5165 { "ServicesResolved", "b", dev_property_get_svc_resolved, NULL, NULL },
5166 { "AdvertisingFlags", "ay", dev_property_get_flags, NULL,
5167 dev_property_flags_exist,
5168 G_DBUS_PROPERTY_FLAG_EXPERIMENTAL},
5169 { "AdvertisingData", "a{yv}", dev_property_get_advertising_data,
5170 NULL, dev_property_advertising_data_exist,
5171 G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
5175 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5176 static const GDBusSignalTable device_signals[] = {
5177 { GDBUS_SIGNAL("Disconnected",
5178 GDBUS_ARGS({ "bdaddr_type", "y" }, { "reason", "y" },
5179 { "name", "s" })) },
5180 { GDBUS_SIGNAL("DeviceConnected", GDBUS_ARGS({ "bdaddr_type", "y"})) },
5181 { GDBUS_SIGNAL("ProfileStateChanged",
5182 GDBUS_ARGS({ "profile", "s"}, {"state", "i"})) },
5183 { GDBUS_SIGNAL("AdvReport",
5184 GDBUS_ARGS({"Address","s"}, { "Address Type", "y" },
5185 { "Adv Type", "y"}, { "RSSI", "i"},
5186 { "AdvDataLen", "i"}, { "AdvData", "ay"})) },
5187 { GDBUS_SIGNAL("LEDataLengthChanged",
5188 GDBUS_ARGS({"max_tx_octets","q"},
5189 { "max_tx_time", "q" },
5190 { "max_rx_octets", "q"},
5191 { "max_rx_time", "q"}))},
5192 { GDBUS_SIGNAL("IpspStateChanged",
5193 GDBUS_ARGS({"connected","b"}, {"if_name","s"}))},
5194 { GDBUS_SIGNAL("OtcDisconnected", NULL)},
5195 { GDBUS_SIGNAL("AttMtuChanged",
5196 GDBUS_ARGS({"mtu", "q"})) },
5201 uint8_t btd_device_get_bdaddr_type(struct btd_device *dev)
5203 return dev->bdaddr_type;
5206 bool btd_device_is_connected(struct btd_device *dev)
5208 return dev->bredr_state.connected || dev->le_state.connected;
5211 void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type)
5213 struct bearer_state *state = get_state(dev, bdaddr_type);
5215 device_update_last_seen(dev, bdaddr_type);
5217 if (state->connected) {
5219 ba2str(&dev->bdaddr, addr);
5220 error("Device %s is already connected", addr);
5224 bacpy(&dev->conn_bdaddr, &dev->bdaddr);
5225 dev->conn_bdaddr_type = dev->bdaddr_type;
5227 /* If this is the first connection over this bearer */
5228 if (bdaddr_type == BDADDR_BREDR)
5229 device_set_bredr_support(dev);
5231 device_set_le_support(dev, bdaddr_type);
5233 state->connected = true;
5235 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
5236 if (dev->le_state.connected && dev->bredr_state.connected)
5239 g_dbus_emit_property_changed(dbus_conn, dev->path, DEVICE_INTERFACE,
5242 #ifdef TIZEN_FEATURE_BLUEZ_BATTERY_WATCH
5243 if (bdaddr_type == BDADDR_BREDR &&
5244 get_charging_state(dev->adapter) == WIRELESS_CHARGING) {
5245 int br_pkt_type = ACL_PTYPE_MASK |
5246 HCI_2DH1 | HCI_2DH3 | HCI_2DH5 |
5247 HCI_3DH1 | HCI_3DH3 | HCI_3DH5;
5249 DBG("During wireless charging... Change packet type");
5250 device_change_pkt_type(dev, (gpointer)br_pkt_type);
5252 #endif /* TIZEN_FEATURE_BLUEZ_BATTERY_WATCH */
5254 g_dbus_emit_signal(dbus_conn, dev->path,
5255 DEVICE_INTERFACE, "DeviceConnected",
5256 DBUS_TYPE_BYTE, &bdaddr_type,
5261 void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type)
5263 struct bearer_state *state = get_state(device, bdaddr_type);
5264 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5265 char *dev_name = device->name;
5268 if (!state->connected)
5271 state->connected = false;
5272 device->general_connect = FALSE;
5274 device_set_svc_refreshed(device, false);
5276 if (device->disconn_timer > 0) {
5277 g_source_remove(device->disconn_timer);
5278 device->disconn_timer = 0;
5281 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5282 if (device->browse) {
5283 struct browse_req *req = device->browse;
5285 if ((bdaddr_type == BDADDR_BREDR && req->search_uuid != 0) ||
5286 (bdaddr_type != BDADDR_BREDR && req->search_uuid == 0))
5287 device->browse = NULL;
5289 DBG("device->browse is for other link");
5293 while (device->disconnects) {
5294 DBusMessage *msg = device->disconnects->data;
5296 g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
5297 device->disconnects = g_slist_remove(device->disconnects, msg);
5298 dbus_message_unref(msg);
5301 if (state->paired && !state->bonded) {
5302 btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
5304 state->paired = false;
5306 /* report change only if both bearers are unpaired */
5307 if (!device->bredr_state.paired && !device->le_state.paired)
5308 g_dbus_emit_property_changed(dbus_conn, device->path,
5314 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
5315 if (device->bredr_state.connected || device->le_state.connected)
5318 g_dbus_emit_property_changed(dbus_conn, device->path,
5319 DEVICE_INTERFACE, "Connected");
5321 g_dbus_emit_signal(dbus_conn, device->path,
5322 DEVICE_INTERFACE, "Disconnected",
5323 DBUS_TYPE_BYTE, &bdaddr_type,
5324 DBUS_TYPE_BYTE, &device->disc_reason,
5325 DBUS_TYPE_STRING, &dev_name,
5330 guint device_add_disconnect_watch(struct btd_device *device,
5331 disconnect_watch watch, void *user_data,
5332 GDestroyNotify destroy)
5334 struct btd_disconnect_data *data;
5335 static guint id = 0;
5337 data = g_new0(struct btd_disconnect_data, 1);
5339 data->watch = watch;
5340 data->user_data = user_data;
5341 data->destroy = destroy;
5343 device->watches = g_slist_append(device->watches, data);
5348 void device_remove_disconnect_watch(struct btd_device *device, guint id)
5352 for (l = device->watches; l; l = l->next) {
5353 struct btd_disconnect_data *data = l->data;
5355 if (data->id == id) {
5356 device->watches = g_slist_remove(device->watches,
5359 data->destroy(data->user_data);
5366 static char *load_cached_name(struct btd_device *device, const char *local,
5369 char filename[PATH_MAX];
5374 if (device_address_is_private(device))
5377 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
5379 key_file = g_key_file_new();
5381 if (!g_key_file_load_from_file(key_file, filename, 0, NULL))
5384 str = g_key_file_get_string(key_file, "General", "Name", NULL);
5387 if (len > HCI_MAX_NAME_LENGTH)
5388 str[HCI_MAX_NAME_LENGTH] = '\0';
5392 g_key_file_free(key_file);
5397 static struct csrk_info *load_csrk(GKeyFile *key_file, const char *group)
5399 struct csrk_info *csrk;
5403 str = g_key_file_get_string(key_file, group, "Key", NULL);
5407 csrk = g_new0(struct csrk_info, 1);
5409 for (i = 0; i < 16; i++) {
5410 if (sscanf(str + (i * 2), "%2hhx", &csrk->key[i]) != 1)
5415 * In case of older storage this will return 0 which is fine since it
5416 * didn't support signing at that point the counter should never have
5419 csrk->counter = g_key_file_get_integer(key_file, group, "Counter",
5431 static void load_services(struct btd_device *device, char **uuids)
5435 for (uuid = uuids; *uuid; uuid++) {
5436 if (g_slist_find_custom(device->uuids, *uuid, bt_uuid_strcmp))
5439 device->uuids = g_slist_insert_sorted(device->uuids,
5447 static void convert_info(struct btd_device *device, GKeyFile *key_file)
5449 char filename[PATH_MAX];
5450 char adapter_addr[18];
5451 char device_addr[18];
5456 /* Load device profile list from legacy properties */
5457 uuids = g_key_file_get_string_list(key_file, "General", "SDPServices",
5460 load_services(device, uuids);
5462 uuids = g_key_file_get_string_list(key_file, "General", "GATTServices",
5465 load_services(device, uuids);
5470 /* Remove old entries so they are not loaded again */
5471 g_key_file_remove_key(key_file, "General", "SDPServices", NULL);
5472 g_key_file_remove_key(key_file, "General", "GATTServices", NULL);
5474 ba2str(btd_adapter_get_address(device->adapter), adapter_addr);
5475 ba2str(&device->bdaddr, device_addr);
5476 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
5479 str = g_key_file_to_data(key_file, &length, NULL);
5480 g_file_set_contents(filename, str, length, NULL);
5483 store_device_info(device);
5486 static void load_info(struct btd_device *device, const char *local,
5487 const char *peer, GKeyFile *key_file)
5490 gboolean store_needed = FALSE;
5493 int source, vendor, product, version;
5495 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5496 gboolean svc_change_regd;
5497 char buf[DEV_MAX_MANUFACTURER_DATA_LEN] = { 0, };
5499 /* Load device name from storage info file, if that fails fall back to
5502 str = g_key_file_get_string(key_file, "General", "Name", NULL);
5504 str = load_cached_name(device, local, peer);
5506 store_needed = TRUE;
5510 strcpy(device->name, str);
5515 device->alias = g_key_file_get_string(key_file, "General", "Alias",
5519 str = g_key_file_get_string(key_file, "General", "Class", NULL);
5523 if (sscanf(str, "%x", &class) == 1)
5524 device->class = class;
5528 /* Load appearance */
5529 str = g_key_file_get_string(key_file, "General", "Appearance", NULL);
5531 device->appearance = strtol(str, NULL, 16);
5535 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5536 /* Load RPA Resolution Support value */
5537 device->rpa_res_support = g_key_file_get_integer(key_file,
5538 "General", "RPAResSupport", NULL);
5540 str = g_key_file_get_string(key_file, "General", "LegacyManufacturerDataLen", NULL);
5542 device->manufacturer_data_len = strtol(str, NULL, 10);
5545 if (0 > device->manufacturer_data_len) {
5546 error("Invalid manufacturer_data_len: %d",
5547 device->manufacturer_data_len);
5548 device->manufacturer_data_len = 0;
5551 str = g_key_file_get_string(key_file, "General", "LegacyManufacturerData", NULL);
5553 if (device->manufacturer_data_len < DEV_MAX_MANUFACTURER_DATA_LEN) {
5554 load_manufacturer_data_2digit(str,
5555 device->manufacturer_data_len, buf);
5556 device->manufacturer_data = g_memdup(buf,
5557 device->manufacturer_data_len);
5563 str = g_key_file_get_string(key_file, "General", "IdentityAddress",
5567 device->rpa = g_malloc0(sizeof(bdaddr_t));
5568 bacpy(device->rpa, &device->bdaddr);
5569 str2ba(str, &device->bdaddr);
5574 /* Load device technology */
5575 techno = g_key_file_get_string_list(key_file, "General",
5576 "SupportedTechnologies", NULL, NULL);
5580 for (t = techno; *t; t++) {
5581 if (g_str_equal(*t, "BR/EDR"))
5582 device->bredr = true;
5583 else if (g_str_equal(*t, "LE"))
5586 error("Unknown device technology");
5590 device->bdaddr_type = BDADDR_BREDR;
5592 str = g_key_file_get_string(key_file, "General",
5593 "AddressType", NULL);
5595 if (str && g_str_equal(str, "public"))
5596 device->bdaddr_type = BDADDR_LE_PUBLIC;
5597 else if (str && g_str_equal(str, "static"))
5598 device->bdaddr_type = BDADDR_LE_RANDOM;
5600 error("Unknown LE device technology");
5604 device->local_csrk = load_csrk(key_file, "LocalSignatureKey");
5605 device->remote_csrk = load_csrk(key_file, "RemoteSignatureKey");
5612 device->trusted = g_key_file_get_boolean(key_file, "General",
5615 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5616 /* Load Trusted Profiles*/
5617 int trusted_profiles = g_key_file_get_integer(key_file, "General",
5618 "TrustedProfiles", NULL);
5619 DBG("Loading TrustedProfiles %d", trusted_profiles);
5620 device->trusted_profiles.pbap = ((trusted_profiles &
5621 (PROFILE_SUPPORTED << PBAP_SHIFT_OFFSET)) >> PBAP_SHIFT_OFFSET);
5622 device->trusted_profiles.map = ((trusted_profiles &
5623 (PROFILE_SUPPORTED << MAP_SHIFT_OFFSET)) >> MAP_SHIFT_OFFSET);
5624 device->trusted_profiles.sap = ((trusted_profiles &
5625 (PROFILE_SUPPORTED << SAP_SHIFT_OFFSET)) >> SAP_SHIFT_OFFSET);
5626 device->trusted_profiles.hfp_hs = ((trusted_profiles &
5627 (PROFILE_SUPPORTED << HFP_HS_SHIFT_OFFSET)) >> HFP_HS_SHIFT_OFFSET);
5628 device->trusted_profiles.a2dp = ((trusted_profiles &
5629 (PROFILE_SUPPORTED << A2DP_SHIFT_OFFSET)) >> A2DP_SHIFT_OFFSET);
5633 /* Load device blocked */
5634 blocked = g_key_file_get_boolean(key_file, "General", "Blocked", NULL);
5636 device_block(device, FALSE);
5638 /* Load device profile list */
5639 uuids = g_key_file_get_string_list(key_file, "General", "Services",
5642 load_services(device, uuids);
5644 /* Discovered services restored from storage */
5645 device->bredr_state.svc_resolved = true;
5648 /* Load device id */
5649 source = g_key_file_get_integer(key_file, "DeviceID", "Source", NULL);
5651 vendor = g_key_file_get_integer(key_file, "DeviceID",
5654 product = g_key_file_get_integer(key_file, "DeviceID",
5657 version = g_key_file_get_integer(key_file, "DeviceID",
5660 btd_device_set_pnpid(device, source, vendor, product, version);
5663 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5664 /* Load Service changed Registered flag */
5665 svc_change_regd = g_key_file_get_boolean(key_file, "Att",
5666 "SvcChangeRegd", NULL);
5668 bt_att_set_svc_changed_indication_registered(device->att,
5673 store_device_info(device);
5676 static void load_att_info(struct btd_device *device, const char *local,
5679 char filename[PATH_MAX];
5681 char *prim_uuid, *str;
5682 char **groups, **handle, *service_uuid;
5683 struct gatt_primary *prim;
5688 sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
5689 prim_uuid = bt_uuid2string(&uuid);
5691 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes", local,
5694 key_file = g_key_file_new();
5695 g_key_file_load_from_file(key_file, filename, 0, NULL);
5696 groups = g_key_file_get_groups(key_file, NULL);
5698 for (handle = groups; *handle; handle++) {
5702 str = g_key_file_get_string(key_file, *handle, "UUID", NULL);
5706 uuid_ok = g_str_equal(str, prim_uuid);
5712 str = g_key_file_get_string(key_file, *handle, "Value", NULL);
5716 end = g_key_file_get_integer(key_file, *handle,
5717 "EndGroupHandle", NULL);
5723 prim = g_new0(struct gatt_primary, 1);
5724 prim->range.start = atoi(*handle);
5725 prim->range.end = end;
5727 switch (strlen(str)) {
5729 uuid.type = SDP_UUID16;
5730 sscanf(str, "%04hx", &uuid.value.uuid16);
5733 uuid.type = SDP_UUID32;
5734 sscanf(str, "%08x", &uuid.value.uuid32);
5737 uuid.type = SDP_UUID128;
5738 memset(tmp, 0, sizeof(tmp));
5739 for (i = 0; i < 16; i++) {
5740 memcpy(tmp, str + (i * 2), 2);
5741 uuid.value.uuid128.data[i] =
5742 (uint8_t) strtol(tmp, NULL, 16);
5751 service_uuid = bt_uuid2string(&uuid);
5752 memcpy(prim->uuid, service_uuid, MAX_LEN_UUID_STR);
5756 device->primaries = g_slist_append(device->primaries, prim);
5760 g_key_file_free(key_file);
5764 static void device_register_primaries(struct btd_device *device,
5765 GSList *prim_list, int psm)
5767 device->primaries = g_slist_concat(device->primaries, prim_list);
5770 static void add_primary(struct gatt_db_attribute *attr, void *user_data)
5772 GSList **new_services = user_data;
5773 struct gatt_primary *prim;
5776 prim = g_new0(struct gatt_primary, 1);
5778 DBG("Failed to allocate gatt_primary structure");
5782 gatt_db_attribute_get_service_handles(attr, &prim->range.start,
5784 gatt_db_attribute_get_service_uuid(attr, &uuid);
5785 bt_uuid_to_string(&uuid, prim->uuid, sizeof(prim->uuid));
5787 *new_services = g_slist_append(*new_services, prim);
5790 static void load_desc_value(struct gatt_db_attribute *attrib,
5791 int err, void *user_data)
5794 warn("loading descriptor value to db failed");
5797 static ssize_t str2val(const char *str, uint8_t *val, size_t len)
5799 const char *pos = str;
5802 for (i = 0; i < len; i++) {
5803 if (sscanf(pos, "%2hhx", &val[i]) != 1)
5811 static int load_desc(char *handle, char *value,
5812 struct gatt_db_attribute *service)
5814 char uuid_str[MAX_LEN_UUID_STR];
5815 struct gatt_db_attribute *att;
5816 uint16_t handle_int;
5818 bt_uuid_t uuid, ext_uuid;
5820 if (sscanf(handle, "%04hx", &handle_int) != 1)
5823 /* Check if there is any value stored, otherwise it is just the UUID */
5824 if (sscanf(value, "%04hx:%s", &val, uuid_str) != 2) {
5825 if (sscanf(value, "%s", uuid_str) != 1)
5830 DBG("loading descriptor handle: 0x%04x, value: 0x%04x, value uuid: %s",
5831 handle_int, val, uuid_str);
5833 bt_string_to_uuid(&uuid, uuid_str);
5834 bt_uuid16_create(&ext_uuid, GATT_CHARAC_EXT_PROPER_UUID);
5836 /* If it is CEP then it must contain the value */
5837 if (!bt_uuid_cmp(&uuid, &ext_uuid) && !val) {
5838 warn("cannot load CEP descriptor without value");
5842 att = gatt_db_service_insert_descriptor(service, handle_int, &uuid,
5843 0, NULL, NULL, NULL);
5844 if (!att || gatt_db_attribute_get_handle(att) != handle_int) {
5845 warn("loading descriptor to db failed");
5850 if (!gatt_db_attribute_write(att, 0, (uint8_t *)&val,
5851 sizeof(val), 0, NULL,
5852 load_desc_value, NULL))
5859 static int load_chrc(char *handle, char *value,
5860 struct gatt_db_attribute *service)
5862 uint16_t properties, value_handle, handle_int;
5863 char uuid_str[MAX_LEN_UUID_STR];
5864 struct gatt_db_attribute *att;
5870 if (sscanf(handle, "%04hx", &handle_int) != 1)
5873 /* Check if there is any value stored */
5874 if (sscanf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hx:%32s:%s",
5875 &value_handle, &properties, val_str, uuid_str) != 4) {
5876 if (sscanf(value, GATT_CHARAC_UUID_STR ":%04hx:%02hx:%s",
5877 &value_handle, &properties, uuid_str) != 3)
5881 val_len = str2val(val_str, val, sizeof(val));
5883 bt_string_to_uuid(&uuid, uuid_str);
5885 /* Log debug message. */
5886 DBG("loading characteristic handle: 0x%04x, value handle: 0x%04x,"
5887 " properties 0x%04x value: %s uuid: %s",
5888 handle_int, value_handle, properties,
5889 val_len ? val_str : "", uuid_str);
5891 att = gatt_db_service_insert_characteristic(service, value_handle,
5892 &uuid, 0, properties,
5894 if (!att || gatt_db_attribute_get_handle(att) != value_handle) {
5895 warn("loading characteristic to db failed");
5900 if (!gatt_db_attribute_write(att, 0, val, val_len, 0, NULL,
5901 load_desc_value, NULL))
5908 static int load_incl(struct gatt_db *db, char *handle, char *value,
5909 struct gatt_db_attribute *service)
5911 char uuid_str[MAX_LEN_UUID_STR];
5912 struct gatt_db_attribute *att;
5913 uint16_t start, end;
5915 if (sscanf(handle, "%04hx", &start) != 1)
5918 if (sscanf(value, GATT_INCLUDE_UUID_STR ":%04hx:%04hx:%s", &start, &end,
5922 /* Log debug message. */
5923 DBG("loading included service: 0x%04x, end: 0x%04x, uuid: %s", start,
5926 att = gatt_db_get_attribute(db, start);
5928 warn("loading included service to db failed - no such service");
5932 att = gatt_db_service_add_included(service, att);
5934 warn("loading included service to db failed");
5941 static int load_service(struct gatt_db *db, char *handle, char *value)
5943 struct gatt_db_attribute *att;
5944 uint16_t start, end;
5945 char type[MAX_LEN_UUID_STR], uuid_str[MAX_LEN_UUID_STR];
5949 if (sscanf(handle, "%04hx", &start) != 1)
5952 if (sscanf(value, "%[^:]:%04hx:%s", type, &end, uuid_str) != 3)
5955 if (g_str_equal(type, GATT_PRIM_SVC_UUID_STR))
5957 else if (g_str_equal(type, GATT_SND_SVC_UUID_STR))
5962 bt_string_to_uuid(&uuid, uuid_str);
5964 /* Log debug message. */
5965 DBG("loading service: 0x%04x, end: 0x%04x, uuid: %s",
5966 start, end, uuid_str);
5968 att = gatt_db_insert_service(db, start, &uuid, primary,
5971 error("Unable load service into db!");
5978 static int load_gatt_db_impl(GKeyFile *key_file, char **keys,
5981 struct gatt_db_attribute *current_service;
5982 char **handle, *value, type[MAX_LEN_UUID_STR];
5985 /* first load service definitions */
5986 for (handle = keys; *handle; handle++) {
5987 value = g_key_file_get_string(key_file, "Attributes", *handle,
5990 if (sscanf(value, "%[^:]:", type) != 1) {
5991 warn("Missing Type in attribute definition");
5996 if (g_str_equal(type, GATT_PRIM_SVC_UUID_STR) ||
5997 g_str_equal(type, GATT_SND_SVC_UUID_STR)) {
5998 ret = load_service(db, *handle, value);
6008 current_service = NULL;
6009 /* then fill them with data*/
6010 for (handle = keys; *handle; handle++) {
6011 value = g_key_file_get_string(key_file, "Attributes", *handle,
6014 if (sscanf(value, "%[^:]:", type) != 1) {
6015 warn("Missing Type in attribute definition");
6020 if (g_str_equal(type, GATT_PRIM_SVC_UUID_STR) ||
6021 g_str_equal(type, GATT_SND_SVC_UUID_STR)) {
6023 uint16_t start, end;
6026 char uuid_str[MAX_LEN_UUID_STR];
6028 if (sscanf(*handle, "%04hx", &tmp) != 1) {
6029 warn("Unable to parse attribute handle");
6034 if (current_service)
6035 gatt_db_service_set_active(current_service,
6038 current_service = gatt_db_get_attribute(db, tmp);
6040 gatt_db_attribute_get_service_data(current_service,
6044 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
6045 } else if (g_str_equal(type, GATT_INCLUDE_UUID_STR)) {
6046 ret = load_incl(db, *handle, value, current_service);
6047 } else if (g_str_equal(type, GATT_CHARAC_UUID_STR)) {
6048 ret = load_chrc(*handle, value, current_service);
6050 ret = load_desc(*handle, value, current_service);
6060 if (current_service)
6061 gatt_db_service_set_active(current_service, true);
6066 static void load_gatt_db(struct btd_device *device, const char *local,
6069 char **keys, filename[PATH_MAX];
6072 if (!gatt_cache_is_enabled(device))
6075 DBG("Restoring %s gatt database from file", peer);
6077 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
6079 key_file = g_key_file_new();
6080 g_key_file_load_from_file(key_file, filename, 0, NULL);
6081 keys = g_key_file_get_keys(key_file, "Attributes", NULL, NULL);
6084 warn("No cache for %s", peer);
6085 g_key_file_free(key_file);
6089 if (load_gatt_db_impl(key_file, keys, device->db))
6090 warn("Unable to load gatt db from file for %s", peer);
6093 g_key_file_free(key_file);
6095 g_slist_free_full(device->primaries, g_free);
6096 device->primaries = NULL;
6097 gatt_db_foreach_service(device->db, NULL, add_primary,
6098 &device->primaries);
6101 static void device_add_uuids(struct btd_device *device, GSList *uuids)
6104 bool changed = false;
6106 for (l = uuids; l != NULL; l = g_slist_next(l)) {
6107 GSList *match = g_slist_find_custom(device->uuids, l->data,
6113 device->uuids = g_slist_insert_sorted(device->uuids,
6119 g_dbus_emit_property_changed(dbus_conn, device->path,
6120 DEVICE_INTERFACE, "UUIDs");
6123 static bool device_match_profile(struct btd_device *device,
6124 struct btd_profile *profile,
6127 if (profile->remote_uuid == NULL)
6130 if (g_slist_find_custom(uuids, profile->remote_uuid,
6131 bt_uuid_strcmp) == NULL) {
6132 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
6133 if (strcmp(profile->name, "hid-device") == 0)
6142 static void add_gatt_service(struct gatt_db_attribute *attr, void *user_data)
6144 struct btd_device *device = user_data;
6145 struct btd_service *service;
6146 struct btd_profile *profile;
6148 char uuid_str[MAX_LEN_UUID_STR];
6151 gatt_db_attribute_get_service_uuid(attr, &uuid);
6152 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
6154 /* Check if service was already probed */
6155 l = find_service_with_uuid(device->services, uuid_str);
6159 /* Add UUID and probe service */
6160 btd_device_add_uuid(device, uuid_str);
6162 /* Check if service was probed */
6163 l = find_service_with_uuid(device->services, uuid_str);
6168 /* Mark service as active to skip discovering it again */
6169 gatt_db_service_set_active(attr, true);
6172 profile = btd_service_get_profile(service);
6174 /* Claim attributes of internal profiles */
6175 if (!profile->external) {
6176 /* Mark the service as claimed by the existing profile. */
6177 gatt_db_service_set_claimed(attr, true);
6180 /* Notify driver about the new connection */
6181 service_accept(service);
6184 static void device_add_gatt_services(struct btd_device *device)
6188 ba2str(&device->bdaddr, addr);
6190 if (device->blocked) {
6191 DBG("Skipping profiles for blocked device %s", addr);
6195 gatt_db_foreach_service(device->db, NULL, add_gatt_service, device);
6198 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6199 static void accept_gatt_service(struct gatt_db_attribute *attr, void *user_data)
6201 struct btd_device *device = user_data;
6204 char uuid_str[MAX_LEN_UUID_STR];
6206 gatt_db_attribute_get_service_uuid(attr, &uuid);
6207 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
6209 l = find_service_with_uuid(device->services, uuid_str);
6213 service_accept(l->data);
6217 static void device_accept_gatt_profiles(struct btd_device *device)
6219 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
6222 for (l = device->services; l != NULL; l = g_slist_next(l))
6223 service_accept(l->data);
6225 gatt_db_foreach_service(device->db, NULL, accept_gatt_service, device);
6229 static void device_remove_gatt_service(struct btd_device *device,
6230 struct gatt_db_attribute *attr)
6232 struct btd_service *service;
6234 char uuid_str[MAX_LEN_UUID_STR];
6237 gatt_db_attribute_get_service_uuid(attr, &uuid);
6238 bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
6240 l = find_service_with_uuid(device->services, uuid_str);
6245 device->services = g_slist_delete_link(device->services, l);
6246 device->pending = g_slist_remove(device->pending, service);
6247 service_remove(service);
6250 static gboolean gatt_services_changed(gpointer user_data)
6252 struct btd_device *device = user_data;
6254 store_gatt_db(device);
6259 static void gatt_service_added(struct gatt_db_attribute *attr, void *user_data)
6261 struct btd_device *device = user_data;
6262 GSList *new_service = NULL;
6263 uint16_t start, end;
6265 if (!bt_gatt_client_is_ready(device->client))
6268 gatt_db_attribute_get_service_data(attr, &start, &end, NULL, NULL);
6270 DBG("start: 0x%04x, end: 0x%04x", start, end);
6273 * TODO: Remove the primaries list entirely once all profiles use
6276 add_primary(attr, &new_service);
6280 device_register_primaries(device, new_service, -1);
6282 add_gatt_service(attr, device);
6284 btd_gatt_client_service_added(device->client_dbus, attr);
6286 gatt_services_changed(device);
6289 static gint prim_attr_cmp(gconstpointer a, gconstpointer b)
6291 const struct gatt_primary *prim = a;
6292 const struct gatt_db_attribute *attr = b;
6293 uint16_t start, end;
6295 gatt_db_attribute_get_service_handles(attr, &start, &end);
6297 return !(prim->range.start == start && prim->range.end == end);
6300 static gint prim_uuid_cmp(gconstpointer a, gconstpointer b)
6302 const struct gatt_primary *prim = a;
6303 const char *uuid = b;
6305 return bt_uuid_strcmp(prim->uuid, uuid);
6308 static void gatt_service_removed(struct gatt_db_attribute *attr,
6311 struct btd_device *device = user_data;
6313 struct gatt_primary *prim;
6314 uint16_t start, end;
6317 * NOTE: shared/gatt-client clears the database in case of failure. This
6318 * triggers the service_removed callback for all affected services.
6319 * Hence, this function will be called in the following cases:
6321 * 1. When a GATT service gets removed due to "Service Changed".
6323 * 2. When a GATT service gets removed when the database get cleared
6324 * upon disconnection with a non-bonded device.
6326 * 3. When a GATT service gets removed when the database get cleared
6327 * by shared/gatt-client when its initialization procedure fails,
6328 * e.g. due to an ATT protocol error or an unexpected disconnect.
6329 * In this case the gatt-client will not be ready.
6332 gatt_db_attribute_get_service_handles(attr, &start, &end);
6334 DBG("start: 0x%04x, end: 0x%04x", start, end);
6336 /* Remove the corresponding gatt_primary */
6337 l = g_slist_find_custom(device->primaries, attr, prim_attr_cmp);
6342 device->primaries = g_slist_delete_link(device->primaries, l);
6345 * Remove the corresponding UUIDs entry and profile, only if this is
6346 * the last service with this UUID.
6348 l = g_slist_find_custom(device->uuids, prim->uuid, bt_uuid_strcmp);
6350 if (l && !g_slist_find_custom(device->primaries, prim->uuid,
6353 * If this happend since the db was cleared for a non-bonded
6354 * device, then don't remove the btd_service just yet. We do
6355 * this so that we can avoid re-probing the profile if the same
6356 * GATT service is found on the device on re-connection.
6357 * However, if the device is marked as temporary, then we
6360 if (device->client || device->temporary == TRUE)
6361 device_remove_gatt_service(device, attr);
6364 device->uuids = g_slist_delete_link(device->uuids, l);
6365 g_dbus_emit_property_changed(dbus_conn, device->path,
6366 DEVICE_INTERFACE, "UUIDs");
6371 store_device_info(device);
6373 btd_gatt_client_service_removed(device->client_dbus, attr);
6375 gatt_services_changed(device);
6378 static struct btd_device *device_new(struct btd_adapter *adapter,
6379 const char *address)
6382 struct btd_device *device;
6383 const char *adapter_path = adapter_get_path(adapter);
6385 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
6386 DBG("address %s", address);
6389 device = g_try_malloc0(sizeof(struct btd_device));
6393 device->tx_power = 127;
6395 device->db = gatt_db_new();
6401 memset(device->ad_flags, INVALID_FLAGS, sizeof(device->ad_flags));
6403 device->ad = bt_ad_new();
6405 device_free(device);
6409 address_up = g_ascii_strup(address, -1);
6410 device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up);
6411 g_strdelimit(device->path, ":", '_');
6414 str2ba(address, &device->bdaddr);
6416 device->client_dbus = btd_gatt_client_new(device);
6417 if (!device->client_dbus) {
6418 error("Failed to create btd_gatt_client");
6419 device_free(device);
6423 DBG("Creating device %s", device->path);
6425 if (g_dbus_register_interface(dbus_conn,
6426 device->path, DEVICE_INTERFACE,
6427 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6428 device_methods, device_signals,
6430 device_methods, NULL,
6432 device_properties, device,
6433 device_free) == FALSE) {
6434 error("Unable to register device interface for %s", address);
6435 device_free(device);
6439 device->adapter = adapter;
6440 device->temporary = true;
6442 device->db_id = gatt_db_register(device->db, gatt_service_added,
6443 gatt_service_removed, device, NULL);
6445 return btd_device_ref(device);
6448 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6449 void device_print_addr(struct btd_device *dev)
6454 ba2str(&dev->bdaddr, ida);
6457 ba2str(dev->rpa, rpa);
6459 DBG("IDA %s [%d] : RPA [%s], BREDR [%d], LE [%d]",
6460 ida, dev->bdaddr_type, rpa,
6461 dev->bredr ? 1 : 0, dev->le ? 1 : 0);
6463 DBG("ADDR %s [%d] : BREDR [%d], LE [%d]",
6464 ida, dev->bdaddr_type,
6465 dev->bredr ? 1 : 0, dev->le ? 1 : 0);
6470 struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
6471 const char *address, GKeyFile *key_file)
6473 struct btd_device *device;
6474 const char *src_dir;
6476 DBG("address %s", address);
6478 device = device_new(adapter, address);
6482 convert_info(device, key_file);
6484 src_dir = btd_adapter_get_storage_dir(adapter);
6486 load_info(device, src_dir, address, key_file);
6487 load_att_info(device, src_dir, address);
6492 struct btd_device *device_create(struct btd_adapter *adapter,
6493 const bdaddr_t *bdaddr, uint8_t bdaddr_type)
6495 struct btd_device *device;
6499 ba2str(bdaddr, dst);
6502 device = device_new(adapter, dst);
6506 device->bdaddr_type = bdaddr_type;
6508 if (bdaddr_type == BDADDR_BREDR)
6509 device->bredr = true;
6513 str = load_cached_name(device, btd_adapter_get_storage_dir(adapter),
6516 strcpy(device->name, str);
6523 char *btd_device_get_storage_path(struct btd_device *device,
6524 const char *filename)
6528 if (device_address_is_private(device)) {
6529 warn("Refusing storage path for private addressed device %s",
6534 ba2str(&device->bdaddr, dstaddr);
6536 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6538 ba2str(device->rpa, dstaddr);
6542 return g_strdup_printf(STORAGEDIR "/%s/%s",
6543 btd_adapter_get_storage_dir(device->adapter),
6546 return g_strdup_printf(STORAGEDIR "/%s/%s/%s",
6547 btd_adapter_get_storage_dir(device->adapter),
6551 void btd_device_device_set_name(struct btd_device *device, const char *name)
6553 if (strncmp(name, device->name, MAX_NAME_LENGTH) == 0)
6556 DBG("%s %s", device->path, name);
6558 strncpy(device->name, name, MAX_NAME_LENGTH);
6560 store_device_info(device);
6562 g_dbus_emit_property_changed(dbus_conn, device->path,
6563 DEVICE_INTERFACE, "Name");
6565 if (device->alias != NULL)
6568 g_dbus_emit_property_changed(dbus_conn, device->path,
6569 DEVICE_INTERFACE, "Alias");
6572 void device_get_name(struct btd_device *device, char *name, size_t len)
6574 if (name != NULL && len > 0) {
6575 strncpy(name, device->name, len - 1);
6576 name[len - 1] = '\0';
6580 bool device_name_known(struct btd_device *device)
6582 return device->name[0] != '\0';
6585 void device_set_class(struct btd_device *device, uint32_t class)
6587 if (device->class == class)
6590 DBG("%s 0x%06X", device->path, class);
6592 device->class = class;
6594 store_device_info(device);
6596 g_dbus_emit_property_changed(dbus_conn, device->path,
6597 DEVICE_INTERFACE, "Class");
6598 g_dbus_emit_property_changed(dbus_conn, device->path,
6599 DEVICE_INTERFACE, "Icon");
6602 void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
6603 uint8_t bdaddr_type)
6605 if (!bacmp(bdaddr, &device->bdaddr) &&
6606 bdaddr_type == device->bdaddr_type)
6609 /* Since this function is only used for LE SMP Identity
6610 * Resolving purposes we can now assume LE is supported.
6614 bacpy(&device->bdaddr, bdaddr);
6615 device->bdaddr_type = bdaddr_type;
6617 store_device_info(device);
6619 g_dbus_emit_property_changed(dbus_conn, device->path,
6620 DEVICE_INTERFACE, "Address");
6621 g_dbus_emit_property_changed(dbus_conn, device->path,
6622 DEVICE_INTERFACE, "AddressType");
6625 void device_set_bredr_support(struct btd_device *device)
6627 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6631 ba2str(device->rpa, addr_str);
6632 error("Cannot set bredr support to RPA device [%s]", addr_str);
6636 if (device->bdaddr_type == BDADDR_LE_RANDOM) {
6637 ba2str(&device->bdaddr, addr_str);
6638 error("Cannot set bredr support to LE random device [%s]",
6647 device->bredr = true;
6648 store_device_info(device);
6651 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6652 void device_set_rpa(struct btd_device *device, const bdaddr_t *rpa)
6654 if (device->rpa == NULL) {
6655 device->rpa = g_malloc0(sizeof(bdaddr_t));
6656 bacpy(device->rpa, rpa);
6658 error("RPA is already set");
6661 void device_set_irk_value(struct btd_device *device, const uint8_t *val)
6663 memcpy(&device->irk_val, val, sizeof(device->irk_val));
6667 void device_set_le_support(struct btd_device *device, uint8_t bdaddr_type)
6673 device->bdaddr_type = bdaddr_type;
6675 store_device_info(device);
6678 void device_update_last_seen(struct btd_device *device, uint8_t bdaddr_type)
6680 if (bdaddr_type == BDADDR_BREDR)
6681 device->bredr_seen = time(NULL);
6683 device->le_seen = time(NULL);
6686 /* It is possible that we have two device objects for the same device in
6687 * case it has first been discovered over BR/EDR and has a private
6688 * address when discovered over LE for the first time. In such a case we
6689 * need to inherit critical values from the duplicate so that we don't
6690 * ovewrite them when writing to storage. The next time bluetoothd
6691 * starts the device will show up as a single instance.
6693 void device_merge_duplicate(struct btd_device *dev, struct btd_device *dup)
6699 dev->bredr = dup->bredr;
6701 dev->trusted = dup->trusted;
6702 dev->blocked = dup->blocked;
6704 for (l = dup->uuids; l; l = g_slist_next(l))
6705 dev->uuids = g_slist_append(dev->uuids, g_strdup(l->data));
6707 if (dev->name[0] == '\0')
6708 strcpy(dev->name, dup->name);
6711 dev->alias = g_strdup(dup->alias);
6713 dev->class = dup->class;
6715 dev->vendor_src = dup->vendor_src;
6716 dev->vendor = dup->vendor;
6717 dev->product = dup->product;
6718 dev->version = dup->version;
6721 uint32_t btd_device_get_class(struct btd_device *device)
6723 return device->class;
6726 uint16_t btd_device_get_vendor(struct btd_device *device)
6728 return device->vendor;
6731 uint16_t btd_device_get_vendor_src(struct btd_device *device)
6733 return device->vendor_src;
6736 uint16_t btd_device_get_product(struct btd_device *device)
6738 return device->product;
6741 uint16_t btd_device_get_version(struct btd_device *device)
6743 return device->version;
6746 static void delete_folder_tree(const char *dirname)
6749 struct dirent *entry;
6750 char filename[PATH_MAX];
6752 dir = opendir(dirname);
6756 while ((entry = readdir(dir)) != NULL) {
6757 if (g_str_equal(entry->d_name, ".") ||
6758 g_str_equal(entry->d_name, ".."))
6761 if (entry->d_type == DT_UNKNOWN)
6762 entry->d_type = util_get_dt(dirname, entry->d_name);
6764 snprintf(filename, PATH_MAX, "%s/%s", dirname, entry->d_name);
6766 if (entry->d_type == DT_DIR)
6767 delete_folder_tree(filename);
6776 static void device_remove_stored(struct btd_device *device)
6778 char device_addr[18];
6779 char filename[PATH_MAX];
6784 if (device->bredr_state.bonded) {
6785 device->bredr_state.bonded = false;
6786 btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
6790 if (device->le_state.bonded) {
6791 device->le_state.bonded = false;
6792 btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
6793 device->bdaddr_type);
6796 device->bredr_state.paired = false;
6797 device->le_state.paired = false;
6799 if (device->blocked)
6800 device_unblock(device, TRUE, FALSE);
6802 ba2str(&device->bdaddr, device_addr);
6804 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6806 ba2str(device->rpa, device_addr);
6809 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s",
6810 btd_adapter_get_storage_dir(device->adapter),
6812 delete_folder_tree(filename);
6814 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
6815 btd_adapter_get_storage_dir(device->adapter),
6818 key_file = g_key_file_new();
6819 g_key_file_load_from_file(key_file, filename, 0, NULL);
6820 g_key_file_remove_group(key_file, "ServiceRecords", NULL);
6822 data = g_key_file_to_data(key_file, &length, NULL);
6824 create_file(filename, S_IRUSR | S_IWUSR);
6825 g_file_set_contents(filename, data, length, NULL);
6829 g_key_file_free(key_file);
6832 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6833 void device_unpair(struct btd_device *device, gboolean remove_stored)
6836 DBG("Unpairing device %s", device->path);
6838 if (device->bonding) {
6841 if (device->bredr_state.connected)
6842 status = MGMT_STATUS_DISCONNECTED;
6844 status = MGMT_STATUS_CONNECT_FAILED;
6846 device_cancel_bonding(device, status);
6850 browse_request_cancel(device->browse);
6853 // while (device->services != NULL) {
6854 // struct btd_service *service = device->services->data;
6856 // device->services = g_slist_remove(device->services, service);
6857 // service_remove(service);
6860 g_slist_free(device->pending);
6861 device->pending = NULL;
6863 if (btd_device_is_connected(device))
6864 disconnect_all(device);
6866 if (device->store_id > 0) {
6867 g_source_remove(device->store_id);
6868 device->store_id = 0;
6871 store_device_info_cb(device);
6875 device_remove_stored(device);
6877 gatt_db_clear(device->db);
6880 bacpy(&device->bdaddr, device->rpa);
6881 device->bdaddr_type = BDADDR_LE_RANDOM;
6883 g_free(device->rpa);
6887 device->bredr_state.paired = 0;
6888 device->le_state.paired = 0;
6889 device->bredr_state.svc_resolved = false;
6890 device->trusted = false;
6891 device->trusted_profiles.pbap = SHOW_AUTHORIZATION;
6892 device->trusted_profiles.map = SHOW_AUTHORIZATION;
6893 device->trusted_profiles.sap = SHOW_AUTHORIZATION;
6894 device->trusted_profiles.hfp_hs = SUPPORTED_TRUSTED;
6895 device->trusted_profiles.a2dp = SUPPORTED_TRUSTED;
6896 if (device->alias != NULL) {
6897 /* Remove alias name because
6898 * In UG if we rename and then unpair device and
6899 * initiates connection without scanning then paired
6900 * list will have alias name as first preference is
6901 * given to alias name.
6903 DBG("Freeing device alias name");
6904 g_free(device->alias);
6905 device->alias = NULL;
6907 g_dbus_emit_property_changed(dbus_conn, device->path,
6908 DEVICE_INTERFACE, "Paired");
6909 // btd_device_unref(device);
6913 void device_remove_stored_folder(struct btd_device *device)
6915 const bdaddr_t *src = btd_adapter_get_address(device->adapter);
6916 char adapter_addr[18];
6917 char device_addr[18];
6918 char filename[PATH_MAX];
6920 ba2str(src, adapter_addr);
6921 ba2str(&device->bdaddr, device_addr);
6923 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s", adapter_addr,
6926 delete_folder_tree(filename);
6930 void device_remove(struct btd_device *device, gboolean remove_stored)
6932 DBG("Removing device %s", device->path);
6934 if (device->bonding) {
6937 if (device->bredr_state.connected)
6938 status = MGMT_STATUS_DISCONNECTED;
6940 status = MGMT_STATUS_CONNECT_FAILED;
6942 device_cancel_bonding(device, status);
6946 browse_request_cancel(device->browse);
6948 while (device->services != NULL) {
6949 struct btd_service *service = device->services->data;
6951 device->services = g_slist_remove(device->services, service);
6952 service_remove(service);
6955 g_slist_free(device->pending);
6956 device->pending = NULL;
6958 if (btd_device_is_connected(device)) {
6959 if (device->disconn_timer > 0)
6960 g_source_remove(device->disconn_timer);
6961 disconnect_all(device);
6964 if (device->store_id > 0) {
6965 g_source_remove(device->store_id);
6966 device->store_id = 0;
6969 store_device_info_cb(device);
6973 device_remove_stored(device);
6975 btd_device_unref(device);
6978 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
6979 int device_rpa_cmp(gconstpointer a, gconstpointer b)
6981 const struct btd_device *device = a;
6982 const char *address = b;
6988 ba2str(device->rpa, addr);
6990 return strcasecmp(addr, address);
6993 int device_addr_cmp(gconstpointer a, gconstpointer b)
6995 const struct btd_device *device = a;
6996 const bdaddr_t *bdaddr = b;
6998 return bacmp(&device->bdaddr, bdaddr);
7001 int device_rpa_ida_cmp(gconstpointer a, gconstpointer b)
7003 const struct btd_device *device = a;
7004 const char *address = b;
7007 if (!device->rpa || device->le == false)
7010 ba2str(&device->bdaddr, addr);
7011 return strcasecmp(addr, address);
7015 int device_address_cmp(gconstpointer a, gconstpointer b)
7017 const struct btd_device *device = a;
7018 const char *address = b;
7021 ba2str(&device->bdaddr, addr);
7022 return strcasecmp(addr, address);
7025 int device_bdaddr_cmp(gconstpointer a, gconstpointer b)
7027 const struct btd_device *device = a;
7028 const bdaddr_t *bdaddr = b;
7030 return bacmp(&device->bdaddr, bdaddr);
7033 static bool addr_is_public(uint8_t addr_type)
7035 if (addr_type == BDADDR_BREDR || addr_type == BDADDR_LE_PUBLIC)
7041 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7042 int device_addr_type_strict_cmp(gconstpointer a, gconstpointer b)
7044 const struct btd_device *dev = a;
7045 const struct device_addr_type *addr = b;
7048 cmp = bacmp(&dev->bdaddr, &addr->bdaddr);
7050 if (addr->bdaddr_type == BDADDR_BREDR) {
7060 if (cmp && dev->rpa && addr->bdaddr_type == BDADDR_LE_RANDOM &&
7061 (addr->bdaddr.b[5] >> 6) == 0x01)
7062 return bacmp(dev->rpa, &addr->bdaddr);
7064 if (addr->bdaddr_type != dev->bdaddr_type)
7071 int device_addr_type_cmp(gconstpointer a, gconstpointer b)
7073 const struct btd_device *dev = a;
7074 const struct device_addr_type *addr = b;
7077 cmp = bacmp(&dev->bdaddr, &addr->bdaddr);
7080 * Address matches and both old and new are public addresses
7081 * (doesn't matter whether LE or BR/EDR, then consider this a
7084 if (!cmp && addr_is_public(addr->bdaddr_type) &&
7085 addr_is_public(dev->bdaddr_type))
7086 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7088 if (dev->rpa && addr->bdaddr_type == BDADDR_BREDR) {
7091 ba2str(&dev->bdaddr, addr_str);
7092 DBG("Don't match. LE Only device [%s]", addr_str);
7101 if (addr->bdaddr_type == BDADDR_BREDR) {
7111 if (addr->bdaddr_type != dev->bdaddr_type) {
7112 if (addr->bdaddr_type == dev->conn_bdaddr_type)
7113 return bacmp(&dev->conn_bdaddr, &addr->bdaddr);
7120 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7121 #ifdef TIZEN_FEATURE_BLUEZ_BATTERY_WATCH
7122 void device_change_pkt_type(gpointer data, gpointer user_data)
7124 int pkt_type = (int)user_data;
7125 struct btd_device *device = data;
7126 struct hci_conn_info_req *cr;
7127 set_conn_ptype_cp cp;
7132 /* Change a packet type only for Phone device */
7133 if ((device->class & 0x00001F00) >> 8 != 0x02)
7136 if (!device->bredr_state.connected)
7139 hdev = hci_open_dev(0);
7141 error("Cannot open hdev");
7145 cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info));
7147 error("Out of memory");
7150 cr->type = ACL_LINK;
7151 bacpy(&cr->bdaddr, &device->bdaddr);
7153 err = ioctl(hdev, HCIGETCONNINFO, cr);
7155 error("Fail to get HCIGETCOINFO");
7157 hci_close_dev(hdev);
7161 cp.handle = cr->conn_info->handle;
7163 cp.pkt_type = cpu_to_le16((uint16_t)pkt_type);
7165 ba2str(&device->bdaddr, addr);
7166 DBG("Handle %d, Addr %s", cp.handle, addr);
7167 DBG("Send Change pkt type request : 0x%X", pkt_type);
7169 if (hci_send_cmd(hdev, OGF_LINK_CTL, OCF_SET_CONN_PTYPE,
7170 SET_CONN_PTYPE_CP_SIZE, &cp) < 0) {
7171 error("hci_send_cmd is failed");
7172 hci_close_dev(hdev);
7176 hci_close_dev(hdev);
7179 #endif /* TIZEN_FEATURE_BLUEZ_BATTERY_WATCH */
7182 static gboolean record_has_uuid(const sdp_record_t *rec,
7183 const char *profile_uuid)
7187 for (pat = rec->pattern; pat != NULL; pat = pat->next) {
7191 uuid = bt_uuid2string(pat->data);
7195 ret = strcasecmp(uuid, profile_uuid);
7206 GSList *btd_device_get_uuids(struct btd_device *device)
7208 return device->uuids;
7212 struct btd_device *dev;
7216 static struct btd_service *probe_service(struct btd_device *device,
7217 struct btd_profile *profile,
7221 struct btd_service *service;
7223 if (profile->device_probe == NULL)
7226 if (!device_match_profile(device, profile, uuids))
7229 l = find_service_with_profile(device->services, profile);
7233 service = service_create(device, profile);
7235 if (service_probe(service)) {
7236 btd_service_unref(service);
7240 /* Only set auto connect if profile has set the flag and can really
7241 * accept connections.
7243 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
7244 if (profile->auto_connect && profile->accept)
7245 device_set_auto_connect(device, TRUE);
7251 static void dev_probe(struct btd_profile *p, void *user_data)
7253 struct probe_data *d = user_data;
7254 struct btd_service *service;
7256 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7257 if (find_service_with_profile(d->dev->services, p)) {
7258 DBG("%s is already probed.(UUID:%s)", p->name, p->remote_uuid);
7263 service = probe_service(d->dev, p, d->uuids);
7267 d->dev->services = g_slist_append(d->dev->services, service);
7270 void device_probe_profile(gpointer a, gpointer b)
7272 struct btd_device *device = a;
7273 struct btd_profile *profile = b;
7274 struct btd_service *service;
7276 service = probe_service(device, profile, device->uuids);
7280 device->services = g_slist_append(device->services, service);
7282 if (!profile->auto_connect || !device->general_connect)
7285 device->pending = g_slist_append(device->pending, service);
7287 if (g_slist_length(device->pending) == 1)
7288 connect_next(device);
7291 void device_remove_profile(gpointer a, gpointer b)
7293 struct btd_device *device = a;
7294 struct btd_profile *profile = b;
7295 struct btd_service *service;
7298 l = find_service_with_profile(device->services, profile);
7299 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
7301 if (g_strcmp0(profile->local_uuid , HID_DEVICE_UUID) == 0) {
7302 l = find_service_with_uuid(device->services,
7309 if (btd_service_get_state(service) ==
7310 BTD_SERVICE_STATE_CONNECTED) {
7312 err = btd_service_disconnect(service);
7314 error("error: %s", strerror(-err));
7325 device->services = g_slist_delete_link(device->services, l);
7326 device->pending = g_slist_remove(device->pending, service);
7327 service_remove(service);
7330 void device_probe_profiles(struct btd_device *device, GSList *uuids)
7332 struct probe_data d = { device, uuids };
7335 ba2str(&device->bdaddr, addr);
7337 if (device->blocked) {
7338 DBG("Skipping profiles for blocked device %s", addr);
7342 DBG("Probing profiles for device %s", addr);
7344 btd_profile_foreach(dev_probe, &d);
7347 device_add_uuids(device, uuids);
7350 static void store_sdp_record(GKeyFile *key_file, sdp_record_t *rec)
7352 char handle_str[11];
7357 sprintf(handle_str, "0x%8.8X", rec->handle);
7359 if (sdp_gen_record_pdu(rec, &buf) < 0)
7362 size = buf.data_size;
7364 str = g_malloc0(size*2+1);
7366 for (i = 0; i < size; i++)
7367 sprintf(str + (i * 2), "%02X", buf.data[i]);
7369 g_key_file_set_string(key_file, "ServiceRecords", handle_str, str);
7375 static void store_primaries_from_sdp_record(GKeyFile *key_file,
7379 char *att_uuid, *prim_uuid;
7380 uint16_t start = 0, end = 0, psm = 0;
7381 char handle[6], uuid_str[33];
7384 sdp_uuid16_create(&uuid, ATT_UUID);
7385 att_uuid = bt_uuid2string(&uuid);
7387 sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
7388 prim_uuid = bt_uuid2string(&uuid);
7390 if (!record_has_uuid(rec, att_uuid))
7393 if (!gatt_parse_record(rec, &uuid, &psm, &start, &end))
7396 sprintf(handle, "%hu", start);
7397 switch (uuid.type) {
7399 sprintf(uuid_str, "%4.4X", uuid.value.uuid16);
7402 sprintf(uuid_str, "%8.8X", uuid.value.uuid32);
7405 for (i = 0; i < 16; i++)
7406 sprintf(uuid_str + (i * 2), "%2.2X",
7407 uuid.value.uuid128.data[i]);
7413 g_key_file_set_string(key_file, handle, "UUID", prim_uuid);
7414 g_key_file_set_string(key_file, handle, "Value", uuid_str);
7415 g_key_file_set_integer(key_file, handle, "EndGroupHandle", end);
7422 static int rec_cmp(const void *a, const void *b)
7424 const sdp_record_t *r1 = a;
7425 const sdp_record_t *r2 = b;
7427 return r1->handle - r2->handle;
7430 static int update_record(struct browse_req *req, const char *uuid,
7435 /* Check for duplicates */
7436 if (sdp_list_find(req->records, rec, rec_cmp))
7440 req->records = sdp_list_append(req->records, sdp_copy_record(rec));
7442 /* Check if UUID is duplicated */
7443 l = g_slist_find_custom(req->device->uuids, uuid, bt_uuid_strcmp);
7445 l = g_slist_find_custom(req->profiles_added, uuid,
7449 req->profiles_added = g_slist_append(req->profiles_added,
7456 static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
7458 struct btd_device *device = req->device;
7460 char srcaddr[18], dstaddr[18];
7461 char sdp_file[PATH_MAX];
7462 char att_file[PATH_MAX];
7463 GKeyFile *sdp_key_file;
7464 GKeyFile *att_key_file;
7468 ba2str(btd_adapter_get_address(device->adapter), srcaddr);
7469 ba2str(&device->bdaddr, dstaddr);
7471 snprintf(sdp_file, PATH_MAX, STORAGEDIR "/%s/cache/%s", srcaddr,
7474 sdp_key_file = g_key_file_new();
7475 g_key_file_load_from_file(sdp_key_file, sdp_file, 0, NULL);
7477 snprintf(att_file, PATH_MAX, STORAGEDIR "/%s/%s/attributes", srcaddr,
7480 att_key_file = g_key_file_new();
7481 g_key_file_load_from_file(att_key_file, att_file, 0, NULL);
7483 for (seq = recs; seq; seq = seq->next) {
7484 sdp_record_t *rec = (sdp_record_t *) seq->data;
7485 sdp_list_t *svcclass = NULL;
7491 if (sdp_get_service_classes(rec, &svcclass) < 0)
7494 /* Check for empty service classes list */
7495 if (svcclass == NULL) {
7496 DBG("Skipping record with no service classes");
7500 /* Extract the first element and skip the remainning */
7501 profile_uuid = bt_uuid2string(svcclass->data);
7502 if (!profile_uuid) {
7503 sdp_list_free(svcclass, free);
7507 if (bt_uuid_strcmp(profile_uuid, PNP_UUID) == 0) {
7508 uint16_t source, vendor, product, version;
7511 pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID_SOURCE);
7512 source = pdlist ? pdlist->val.uint16 : 0x0000;
7514 pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
7515 vendor = pdlist ? pdlist->val.uint16 : 0x0000;
7517 pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
7518 product = pdlist ? pdlist->val.uint16 : 0x0000;
7520 pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
7521 version = pdlist ? pdlist->val.uint16 : 0x0000;
7523 if (source || vendor || product || version)
7524 btd_device_set_pnpid(device, source, vendor,
7528 if (update_record(req, profile_uuid, rec) < 0)
7532 store_sdp_record(sdp_key_file, rec);
7535 store_primaries_from_sdp_record(att_key_file, rec);
7539 sdp_list_free(svcclass, free);
7543 data = g_key_file_to_data(sdp_key_file, &length, NULL);
7545 create_file(sdp_file, S_IRUSR | S_IWUSR);
7546 g_file_set_contents(sdp_file, data, length, NULL);
7550 g_key_file_free(sdp_key_file);
7554 data = g_key_file_to_data(att_key_file, &length, NULL);
7556 create_file(att_file, S_IRUSR | S_IWUSR);
7557 g_file_set_contents(att_file, data, length, NULL);
7561 g_key_file_free(att_key_file);
7565 static int primary_cmp(gconstpointer a, gconstpointer b)
7567 return memcmp(a, b, sizeof(struct gatt_primary));
7570 static void update_gatt_uuids(struct browse_req *req, GSList *current,
7575 /* Added Profiles */
7576 for (l = found; l; l = g_slist_next(l)) {
7577 struct gatt_primary *prim = l->data;
7580 lmatch = g_slist_find_custom(current, prim, primary_cmp);
7585 req->profiles_added = g_slist_append(req->profiles_added,
7586 g_strdup(prim->uuid));
7588 DBG("UUID Added: %s", prim->uuid);
7592 static GSList *device_services_from_record(struct btd_device *device,
7595 GSList *l, *prim_list = NULL;
7599 sdp_uuid16_create(&proto_uuid, ATT_UUID);
7600 att_uuid = bt_uuid2string(&proto_uuid);
7602 for (l = profiles; l; l = l->next) {
7603 const char *profile_uuid = l->data;
7604 const sdp_record_t *rec;
7605 struct gatt_primary *prim;
7606 uint16_t start = 0, end = 0, psm = 0;
7609 rec = btd_device_get_record(device, profile_uuid);
7613 if (!record_has_uuid(rec, att_uuid))
7616 if (!gatt_parse_record(rec, &prim_uuid, &psm, &start, &end))
7619 prim = g_new0(struct gatt_primary, 1);
7620 prim->range.start = start;
7621 prim->range.end = end;
7622 sdp_uuid2strn(&prim_uuid, prim->uuid, sizeof(prim->uuid));
7624 prim_list = g_slist_append(prim_list, prim);
7632 static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
7634 struct browse_req *req = user_data;
7635 struct btd_device *device = req->device;
7639 ba2str(&device->bdaddr, addr);
7642 error("%s: error updating services: %s (%d)",
7643 addr, strerror(-err), -err);
7647 update_bredr_services(req, recs);
7649 if (device->tmp_records)
7650 sdp_list_free(device->tmp_records,
7651 (sdp_free_func_t) sdp_record_free);
7653 device->tmp_records = req->records;
7654 req->records = NULL;
7656 if (!req->profiles_added) {
7657 DBG("%s: No service update", addr);
7661 primaries = device_services_from_record(device, req->profiles_added);
7663 device_register_primaries(device, primaries, ATT_PSM);
7666 * TODO: The btd_service instances for GATT services need to be
7667 * initialized with the service handles. Eventually this code should
7668 * perform ATT protocol service discovery over the ATT PSM to obtain
7669 * the full list of services and populate a client-role gatt_db over
7672 device_probe_profiles(device, req->profiles_added);
7674 /* Propagate services changes */
7675 g_dbus_emit_property_changed(dbus_conn, req->device->path,
7676 DEVICE_INTERFACE, "UUIDs");
7679 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7683 /* since no new services are found, UUID signal is not emitted,
7684 ** so send a reply to the framework with the existing services */
7685 if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
7686 "DiscoverServices"))
7687 discover_services_reply(req, err, device->tmp_records);
7692 device_svc_resolved(device, BROWSE_SDP, BDADDR_BREDR, err);
7695 static void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
7697 struct browse_req *req = user_data;
7698 struct btd_device *device = req->device;
7699 struct btd_adapter *adapter = device->adapter;
7702 /* If we have a valid response and req->search_uuid == 2, then L2CAP
7703 * UUID & PNP searching was successful -- we are done */
7704 if (err < 0 || (req->search_uuid == 2 && req->records)) {
7705 if (err == -ECONNRESET && req->reconnect_attempt < 1) {
7707 req->reconnect_attempt++;
7712 update_bredr_services(req, recs);
7714 /* Search for mandatory uuids */
7715 if (uuid_list[req->search_uuid]) {
7716 sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
7717 bt_search_service(btd_adapter_get_address(adapter),
7718 &device->bdaddr, &uuid,
7719 browse_cb, user_data, NULL,
7725 search_cb(recs, err, user_data);
7728 static bool device_get_auto_connect(struct btd_device *device)
7730 if (device->disable_auto_connect)
7733 return device->auto_connect;
7736 static void disconnect_gatt_service(gpointer data, gpointer user_data)
7738 struct btd_service *service = data;
7739 struct btd_profile *profile = btd_service_get_profile(service);
7741 /* Ignore if profile cannot accept connections */
7742 if (!profile->accept)
7745 btd_service_disconnect(service);
7748 static void att_disconnected_cb(int err, void *user_data)
7750 struct btd_device *device = user_data;
7757 DBG("%s (%d)", strerror(err), err);
7759 g_slist_foreach(device->services, disconnect_gatt_service, NULL);
7761 btd_gatt_client_disconnected(device->client_dbus);
7763 if (!device_get_auto_connect(device)) {
7764 DBG("Automatic connection disabled");
7769 * Keep scanning/re-connection active if disconnection reason
7770 * is connection timeout, remote user terminated connection or local
7771 * initiated disconnection.
7773 if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
7774 adapter_connect_list_add(device->adapter, device);
7777 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7778 device_set_gatt_connected(device, FALSE);
7780 attio_cleanup(device);
7783 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7784 static void att_mtu_changed(uint16_t mtu, void *user_data)
7786 struct btd_device *device = user_data;
7788 DBG("att mtu changed %d", mtu);
7790 g_dbus_emit_signal(dbus_conn, device->path,
7791 DEVICE_INTERFACE, "AttMtuChanged",
7792 DBUS_TYPE_UINT16, &mtu,
7797 static void register_gatt_services(struct btd_device *device)
7799 struct browse_req *req = device->browse;
7800 GSList *services = NULL;
7802 if (!bt_gatt_client_is_ready(device->client))
7806 * TODO: Remove the primaries list entirely once all profiles use
7809 gatt_db_foreach_service(device->db, NULL, add_primary, &services);
7811 btd_device_set_temporary(device, false);
7813 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7815 if (req->search_uuid)
7816 DBG("browse req. is for SDP. Ignore it.");
7818 update_gatt_uuids(req, device->primaries, services);
7822 update_gatt_uuids(req, device->primaries, services);
7825 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
7826 /* do not delete existing primary list,
7827 * just append the new primary uuids,
7828 * the list will be modifed when service changed
7829 * indication is received during connection */
7830 g_slist_free_full(device->primaries, g_free);
7831 device->primaries = NULL;
7834 device_register_primaries(device, services, -1);
7836 device_add_gatt_services(device);
7839 static void gatt_client_init(struct btd_device *device);
7841 static void gatt_client_ready_cb(bool success, uint8_t att_ecode,
7844 struct btd_device *device = user_data;
7846 DBG("status: %s, error: %u", success ? "success" : "failed", att_ecode);
7849 device_svc_resolved(device, BROWSE_GATT, device->bdaddr_type,
7854 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
7855 /* Register the services after setting the client is ready
7856 * and exporting all the services and characteristics paths.
7858 register_gatt_services(device);
7861 btd_gatt_client_ready(device->client_dbus);
7862 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7863 register_gatt_services(device);
7866 device_svc_resolved(device, BROWSE_GATT, device->bdaddr_type, 0);
7868 store_gatt_db(device);
7870 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7871 if (device->name[0] == '\0') {
7873 name = bt_gatt_client_get_gap_device_name(device->client);
7875 strncpy(device->name, name, MAX_NAME_LENGTH);
7880 static void gatt_client_service_changed(uint16_t start_handle,
7881 uint16_t end_handle,
7884 DBG("start 0x%04x, end: 0x%04x", start_handle, end_handle);
7887 static void gatt_debug(const char *str, void *user_data)
7892 static void gatt_client_init(struct btd_device *device)
7894 gatt_client_cleanup(device);
7896 if (!device->connect && !main_opts.reverse_discovery) {
7897 DBG("Reverse service discovery disabled: skipping GATT client");
7901 device->client = bt_gatt_client_new(device->db, device->att,
7903 if (!device->client) {
7904 DBG("Failed to initialize");
7908 bt_gatt_client_set_debug(device->client, gatt_debug, NULL, NULL);
7911 * Notify notify existing service about the new connection so they can
7912 * react to notifications while discovering services
7914 device_accept_gatt_profiles(device);
7916 device->gatt_ready_id = bt_gatt_client_ready_register(device->client,
7917 gatt_client_ready_cb,
7919 if (!device->gatt_ready_id) {
7920 DBG("Failed to register GATT ready callback");
7921 gatt_client_cleanup(device);
7925 if (!bt_gatt_client_set_service_changed(device->client,
7926 gatt_client_service_changed,
7928 DBG("Failed to set service changed handler");
7929 gatt_client_cleanup(device);
7933 btd_gatt_client_connected(device->client_dbus);
7936 static void gatt_server_init(struct btd_device *device,
7937 struct btd_gatt_database *database)
7939 struct gatt_db *db = btd_gatt_database_get_db(database);
7942 error("No local GATT database exists for this adapter");
7946 gatt_server_cleanup(device);
7948 device->server = bt_gatt_server_new(db, device->att, device->att_mtu,
7949 main_opts.key_size);
7950 if (!device->server) {
7951 error("Failed to initialize bt_gatt_server");
7955 bt_att_set_enc_key_size(device->att, device->ltk_enc_size);
7957 bt_gatt_server_set_debug(device->server, gatt_debug, NULL, NULL);
7959 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7960 if (!bt_gatt_server_set_mtu_changed(device->server,
7963 DBG("Failed to set mtu changed handler");
7969 static bool local_counter(uint32_t *sign_cnt, void *user_data)
7971 struct btd_device *dev = user_data;
7973 if (!dev->local_csrk)
7976 *sign_cnt = dev->local_csrk->counter++;
7978 store_device_info(dev);
7983 static bool remote_counter(uint32_t *sign_cnt, void *user_data)
7985 struct btd_device *dev = user_data;
7987 if (!dev->remote_csrk || *sign_cnt < dev->remote_csrk->counter)
7990 dev->remote_csrk->counter = *sign_cnt;
7992 store_device_info(dev);
7997 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
7998 static bool load_svc_change_indication_status(struct btd_device *device, const char *local,
8001 char filename[PATH_MAX];
8003 gboolean svc_change_regd = false;
8004 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
8006 key_file = g_key_file_new();
8007 if (!g_key_file_load_from_file(key_file, filename, 0, NULL))
8010 /* Load Service changed Registered flag */
8011 svc_change_regd = g_key_file_get_boolean(key_file, "Att",
8012 "SvcChangeRegd", NULL);
8013 bt_att_set_svc_changed_indication_registered(device->att,
8018 g_key_file_free(key_file);
8020 return svc_change_regd;
8024 bool device_attach_att(struct btd_device *dev, GIOChannel *io)
8026 GError *gerr = NULL;
8028 BtIOSecLevel sec_level;
8031 struct btd_gatt_database *database;
8032 const bdaddr_t *dst;
8034 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8035 uint8_t dst_type = BDADDR_BREDR;
8037 const bdaddr_t *src;
8040 bt_io_get(io, &gerr, BT_IO_OPT_SEC_LEVEL, &sec_level,
8041 BT_IO_OPT_IMTU, &mtu,
8042 BT_IO_OPT_CID, &cid,
8043 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8044 BT_IO_OPT_DEST_TYPE, &dst_type,
8049 error("bt_io_get: %s", gerr->message);
8054 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
8055 if (sec_level == BT_IO_SEC_LOW && dev->le_state.paired) {
8056 DBG("Elevating security level since LTK is available");
8058 sec_level = BT_IO_SEC_MEDIUM;
8059 bt_io_set(io, &gerr, BT_IO_OPT_SEC_LEVEL, sec_level,
8062 error("bt_io_set: %s", gerr->message);
8069 dev->att_mtu = MIN(mtu, main_opts.gatt_mtu);
8070 attrib = g_attrib_new(io,
8071 cid == ATT_CID ? BT_ATT_DEFAULT_LE_MTU : dev->att_mtu,
8074 error("Unable to create new GAttrib instance");
8078 dev->attrib = attrib;
8079 dev->att = g_attrib_get_att(attrib);
8081 bt_att_ref(dev->att);
8083 dev->att_disconn_id = bt_att_register_disconnect(dev->att,
8084 att_disconnected_cb, dev, NULL);
8085 bt_att_set_close_on_unref(dev->att, true);
8087 if (dev->local_csrk)
8088 bt_att_set_local_key(dev->att, dev->local_csrk->key,
8089 local_counter, dev);
8091 if (dev->remote_csrk)
8092 bt_att_set_remote_key(dev->att, dev->remote_csrk->key,
8093 remote_counter, dev);
8095 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8096 if (dst_type != BDADDR_BREDR && device_get_rpa_exist(dev) == true) {
8097 bt_att_set_remote_addr(dev->att,
8098 device_get_rpa(dev), BDADDR_LE_RANDOM);
8100 bt_att_set_remote_addr(dev->att,
8101 &dev->bdaddr, dev->bdaddr_type);
8105 database = btd_adapter_get_database(dev->adapter);
8107 dst = device_get_address(dev);
8108 ba2str(dst, dstaddr);
8110 if (gatt_db_isempty(dev->db))
8111 load_gatt_db(dev, btd_adapter_get_storage_dir(dev->adapter),
8114 gatt_client_init(dev);
8115 gatt_server_init(dev, database);
8118 * Remove the device from the connect_list and give the passive
8119 * scanning another chance to be restarted in case there are
8120 * other devices in the connect_list.
8122 adapter_connect_list_remove(dev->adapter, dev);
8124 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8125 src = btd_adapter_get_address(dev->adapter);
8126 ba2str(src, srcaddr);
8128 /* load the service changed indication status on connection */
8129 load_svc_change_indication_status(dev, srcaddr, dstaddr);
8135 static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
8137 struct btd_device *device = user_data;
8142 g_io_channel_unref(device->att_io);
8143 device->att_io = NULL;
8146 DBG("%s", gerr->message);
8148 if (g_error_matches(gerr, BT_IO_ERROR, ECONNABORTED))
8151 if (device_get_auto_connect(device)) {
8152 DBG("Enabling automatic connections");
8153 adapter_connect_list_add(device->adapter, device);
8157 browse_request_complete(device->browse,
8159 device->bdaddr_type,
8162 err = -ECONNABORTED;
8166 if (!device_attach_att(device, io))
8169 if (!device->bonding)
8172 if (device->bonding->agent)
8173 io_cap = agent_get_io_capability(device->bonding->agent);
8175 io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
8177 err = adapter_create_bonding(device->adapter, &device->bdaddr,
8178 device->bdaddr_type, io_cap);
8180 if (device->bonding && err < 0) {
8181 reply = btd_error_failed(device->bonding->msg, strerror(-err));
8182 g_dbus_send_message(dbus_conn, reply);
8183 bonding_request_cancel(device->bonding);
8184 bonding_request_free(device->bonding);
8188 device_browse_gatt(device, NULL);
8190 if (device->connect) {
8192 reply = btd_error_failed(device->connect,
8195 reply = dbus_message_new_method_return(device->connect);
8197 g_dbus_send_message(dbus_conn, reply);
8198 dbus_message_unref(device->connect);
8199 device->connect = NULL;
8203 int device_connect_le(struct btd_device *dev)
8205 struct btd_adapter *adapter = dev->adapter;
8206 BtIOSecLevel sec_level;
8208 GError *gerr = NULL;
8211 /* There is one connection attempt going on */
8215 ba2str(&dev->bdaddr, addr);
8217 DBG("Connection attempt to: %s", addr);
8219 if (dev->le_state.paired)
8220 sec_level = BT_IO_SEC_MEDIUM;
8222 sec_level = BT_IO_SEC_LOW;
8225 * This connection will help us catch any PDUs that comes before
8228 io = bt_io_connect(att_connect_cb, dev, NULL, &gerr,
8229 BT_IO_OPT_SOURCE_BDADDR,
8230 btd_adapter_get_address(adapter),
8231 BT_IO_OPT_SOURCE_TYPE,
8232 btd_adapter_get_address_type(adapter),
8233 BT_IO_OPT_DEST_BDADDR, &dev->bdaddr,
8234 BT_IO_OPT_DEST_TYPE, dev->bdaddr_type,
8235 BT_IO_OPT_CID, ATT_CID,
8236 BT_IO_OPT_SEC_LEVEL, sec_level,
8241 DBusMessage *reply = btd_error_failed(
8242 dev->bonding->msg, gerr->message);
8244 g_dbus_send_message(dbus_conn, reply);
8245 bonding_request_cancel(dev->bonding);
8246 bonding_request_free(dev->bonding);
8249 error("ATT bt_io_connect(%s): %s", addr, gerr->message);
8254 /* Keep this, so we can cancel the connection */
8260 static struct browse_req *browse_request_new(struct btd_device *device,
8264 struct browse_req *req;
8269 req = g_new0(struct browse_req, 1);
8270 req->device = device;
8273 device->browse = req;
8278 req->msg = dbus_message_ref(msg);
8281 * Track the request owner to cancel it automatically if the owner
8284 req->listener_id = g_dbus_add_disconnect_watch(dbus_conn,
8285 dbus_message_get_sender(msg),
8286 browse_request_exit,
8292 static int device_browse_gatt(struct btd_device *device, DBusMessage *msg)
8294 struct btd_adapter *adapter = device->adapter;
8295 struct browse_req *req;
8297 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8300 req = browse_request_new(device, BROWSE_GATT, msg);
8304 if (device->client) {
8306 * If discovery has not yet completed, then wait for gatt-client
8309 if (!bt_gatt_client_is_ready(device->client))
8313 * Services have already been discovered, so signal this browse
8314 * request as resolved.
8316 device_svc_resolved(device, BROWSE_GATT, device->bdaddr_type,
8321 device->att_io = bt_io_connect(att_connect_cb,
8323 BT_IO_OPT_SOURCE_BDADDR,
8324 btd_adapter_get_address(adapter),
8325 BT_IO_OPT_SOURCE_TYPE,
8326 btd_adapter_get_address_type(adapter),
8327 BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
8328 BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
8329 BT_IO_OPT_CID, ATT_CID,
8330 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
8333 if (device->att_io == NULL) {
8334 browse_request_free(req);
8341 static uint16_t get_sdp_flags(struct btd_device *device)
8345 vid = btd_device_get_vendor(device);
8346 pid = btd_device_get_product(device);
8348 /* Sony DualShock 4 is not respecting negotiated L2CAP MTU. This might
8349 * results in SDP response being dropped by kernel. Workaround this by
8350 * forcing SDP code to use bigger MTU while connecting.
8352 if (vid == 0x054c && pid == 0x05c4)
8353 return SDP_LARGE_MTU;
8355 if (btd_adapter_ssp_enabled(device->adapter))
8358 /* if no EIR try matching Sony DualShock 4 with name and class */
8359 if (!strncmp(device->name, "Wireless Controller", MAX_NAME_LENGTH) &&
8360 device->class == 0x2508)
8361 return SDP_LARGE_MTU;
8366 static int device_browse_sdp(struct btd_device *device, DBusMessage *msg)
8368 struct btd_adapter *adapter = device->adapter;
8369 struct browse_req *req;
8373 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8376 req = browse_request_new(device, BROWSE_SDP, msg);
8380 sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
8382 req->sdp_flags = get_sdp_flags(device);
8384 err = bt_search_service(btd_adapter_get_address(adapter),
8385 &device->bdaddr, &uuid, browse_cb, req, NULL,
8388 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8389 device->browse = NULL;
8391 browse_request_free(req);
8398 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8399 void device_set_last_addr_type(struct btd_device *device, uint8_t type)
8404 //DBG("Last addr type %d", type);
8406 device->last_bdaddr_type = type;
8409 gboolean device_is_ipsp_connected(struct btd_device * device)
8411 return device->ipsp_connected;
8414 void device_set_ipsp_connected(struct btd_device *device, gboolean connected,
8415 const unsigned char *ifname)
8417 char *iface_name = NULL;
8419 if (device == NULL) {
8420 error("device is NULL");
8424 if (device->ipsp_connected == connected)
8427 device->ipsp_connected = connected;
8429 memset(device->if_name, 0, sizeof(device->if_name));
8430 memcpy(device->if_name, ifname, 16);
8431 iface_name = device->if_name;
8433 DBG("ipsp_connected %d", connected);
8434 DBG("ipsp_iface: %s is Up !", iface_name);
8436 g_dbus_emit_signal(dbus_conn, device->path,
8437 DEVICE_INTERFACE, "IpspStateChanged",
8438 DBUS_TYPE_BOOLEAN, &connected,
8439 DBUS_TYPE_STRING, &iface_name,
8442 void device_le_data_length_changed(struct btd_device *device, uint16_t max_tx_octets,
8443 uint16_t max_tx_time, uint16_t max_rx_octets, uint16_t max_rx_time)
8445 if (device == NULL) {
8446 error("device is NULL");
8450 device->max_tx_octets = max_tx_octets;
8451 device->max_tx_time = max_tx_time;
8452 device->max_rx_octets = max_rx_octets;
8453 device->max_rx_time = max_rx_time;
8455 DBG("data length changed values :max_tx_octets: %d max_tx_time: %d max_rx_octets: %d max_rx_time: %d",
8456 max_tx_octets, max_tx_time, max_rx_octets, max_rx_time);
8458 g_dbus_emit_signal(dbus_conn, device->path,
8459 DEVICE_INTERFACE, "LEDataLengthChanged",
8460 DBUS_TYPE_UINT16, &max_tx_octets,
8461 DBUS_TYPE_UINT16, &max_tx_time,
8462 DBUS_TYPE_UINT16, &max_rx_octets,
8463 DBUS_TYPE_UINT16, &max_rx_time,
8467 const bdaddr_t *device_get_rpa(struct btd_device *device)
8472 const uint8_t *device_get_irk_value(struct btd_device *device)
8474 return device->irk_val;
8477 bool device_get_rpa_exist(struct btd_device *device)
8479 return device->rpa ? true : false;
8482 void device_set_auth_addr_type(struct btd_device *device, uint8_t type)
8487 DBG("Auth addr type %d", type);
8489 device->auth_bdaddr_type = type;
8492 void device_get_tizen_addr(struct btd_device *device, uint8_t type,
8493 struct device_addr_type *addr)
8495 if (!device || !addr)
8498 if (type == BDADDR_BREDR) {
8499 bacpy(&addr->bdaddr, &device->bdaddr);
8500 addr->bdaddr_type = BDADDR_BREDR;
8505 bacpy(&addr->bdaddr, device->rpa);
8506 addr->bdaddr_type = BDADDR_LE_RANDOM;
8510 bacpy(&addr->bdaddr, &device->bdaddr);
8511 addr->bdaddr_type = device->bdaddr_type;
8515 int device_discover_services(struct btd_device *device)
8520 err = device_browse_sdp(device, NULL);
8522 err = device_browse_gatt(device, NULL);
8524 if (err == 0 && device->discov_timer) {
8525 g_source_remove(device->discov_timer);
8526 device->discov_timer = 0;
8532 struct btd_adapter *device_get_adapter(struct btd_device *device)
8537 return device->adapter;
8540 const bdaddr_t *device_get_address(struct btd_device *device)
8542 return &device->bdaddr;
8544 uint8_t device_get_le_address_type(struct btd_device *device)
8546 return device->bdaddr_type;
8549 const char *device_get_path(const struct btd_device *device)
8554 return device->path;
8557 gboolean device_is_temporary(struct btd_device *device)
8559 return device->temporary;
8562 void btd_device_set_temporary(struct btd_device *device, bool temporary)
8567 if (device->temporary == temporary)
8570 if (device_address_is_private(device))
8573 DBG("temporary %d", temporary);
8575 device->temporary = temporary;
8579 adapter_whitelist_remove(device->adapter, device);
8580 adapter_connect_list_remove(device->adapter, device);
8585 adapter_whitelist_add(device->adapter, device);
8587 store_device_info(device);
8589 /* attributes were not stored when resolved if device was temporary */
8590 if (device->bdaddr_type != BDADDR_BREDR &&
8591 device->le_state.svc_resolved &&
8592 g_slist_length(device->primaries) != 0)
8593 store_services(device);
8596 void btd_device_set_trusted(struct btd_device *device, gboolean trusted)
8601 if (device->trusted == trusted)
8604 DBG("trusted %d", trusted);
8606 device->trusted = trusted;
8608 store_device_info(device);
8610 g_dbus_emit_property_changed(dbus_conn, device->path,
8611 DEVICE_INTERFACE, "Trusted");
8614 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8615 void device_disconnect_blocked(struct btd_device *device, char *uuid)
8617 struct btd_service *service;
8620 if (!device || !uuid)
8623 l = find_service_with_uuid(device->services, uuid);
8628 if (btd_service_get_state(service) ==
8629 BTD_SERVICE_STATE_CONNECTED) {
8631 err = btd_service_disconnect(service);
8633 error("error: %s", strerror(-err));
8637 void btd_device_set_trusted_profiles(struct btd_device *device,
8638 uint32_t pbap, uint32_t map, uint32_t sap,
8639 uint32_t hfp_hs, uint32_t a2dp)
8644 DBG("TrustedProfiles Parameters: [PBAP %d] [MAP %d] [SAP %d] [HFP %d] [A2DP %d]",
8645 pbap, map, sap, hfp_hs, a2dp);
8647 if (device->trusted_profiles.pbap == pbap &&
8648 device->trusted_profiles.map == map &&
8649 device->trusted_profiles.sap == sap &&
8650 device->trusted_profiles.hfp_hs == hfp_hs &&
8651 device->trusted_profiles.a2dp == a2dp)
8654 /* Disconnect OBEX based profiles if connected */
8655 if (device->trusted_profiles.pbap != pbap) {
8656 device->trusted_profiles.pbap = pbap;
8657 if (pbap == SUPPORTED_BLOCKED)
8658 device_disconnect_blocked(device, OBEX_PSE_UUID);
8659 } else if (device->trusted_profiles.map != map) {
8660 device->trusted_profiles.map = map;
8661 if (map == SUPPORTED_BLOCKED)
8662 device_disconnect_blocked(device, OBEX_MAP_UUID);
8663 } else if (device->trusted_profiles.sap != sap) {
8664 device->trusted_profiles.sap = sap;
8665 if (sap == SUPPORTED_BLOCKED)
8666 device_disconnect_blocked(device, SAP_UUID);
8667 } else if (device->trusted_profiles.hfp_hs != hfp_hs) {
8668 device->trusted_profiles.hfp_hs = hfp_hs;
8669 } else if (device->trusted_profiles.a2dp != a2dp) {
8670 device->trusted_profiles.a2dp = a2dp;
8673 store_device_info(device);
8674 g_dbus_emit_property_changed(dbus_conn, device->path,
8675 DEVICE_INTERFACE, "TrustedProfiles");
8679 void device_set_bonded(struct btd_device *device, uint8_t bdaddr_type)
8686 if (bdaddr_type == BDADDR_BREDR)
8687 device->bredr_state.bonded = true;
8689 device->le_state.bonded = true;
8691 btd_device_set_temporary(device, false);
8694 void device_set_legacy(struct btd_device *device, bool legacy)
8699 DBG("legacy %d", legacy);
8701 if (device->legacy == legacy)
8704 device->legacy = legacy;
8706 g_dbus_emit_property_changed(dbus_conn, device->path,
8707 DEVICE_INTERFACE, "LegacyPairing");
8710 void device_store_svc_chng_ccc(struct btd_device *device, uint8_t bdaddr_type,
8713 char filename[PATH_MAX];
8714 char device_addr[18];
8720 ba2str(&device->bdaddr, device_addr);
8721 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
8722 btd_adapter_get_storage_dir(device->adapter),
8725 key_file = g_key_file_new();
8726 g_key_file_load_from_file(key_file, filename, 0, NULL);
8728 /* for bonded devices this is done on every connection so limit writes
8729 * to storage if no change needed
8731 if (bdaddr_type == BDADDR_BREDR) {
8732 old_value = g_key_file_get_integer(key_file, "ServiceChanged",
8733 "CCC_BR/EDR", NULL);
8734 if (old_value == value)
8737 g_key_file_set_integer(key_file, "ServiceChanged", "CCC_BR/EDR",
8740 old_value = g_key_file_get_integer(key_file, "ServiceChanged",
8742 if (old_value == value)
8745 g_key_file_set_integer(key_file, "ServiceChanged", "CCC_LE",
8749 create_file(filename, S_IRUSR | S_IWUSR);
8751 str = g_key_file_to_data(key_file, &length, NULL);
8752 g_file_set_contents(filename, str, length, NULL);
8756 g_key_file_free(key_file);
8758 void device_load_svc_chng_ccc(struct btd_device *device, uint16_t *ccc_le,
8759 uint16_t *ccc_bredr)
8761 char filename[PATH_MAX];
8762 char device_addr[18];
8765 ba2str(&device->bdaddr, device_addr);
8766 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
8767 btd_adapter_get_storage_dir(device->adapter),
8770 key_file = g_key_file_new();
8771 g_key_file_load_from_file(key_file, filename, 0, NULL);
8774 * If there is no "ServiceChanged" section we may be loading data from
8775 * old version which did not persist Service Changed CCC values. Let's
8776 * check if we are bonded and assume indications were enabled by peer
8777 * in such case - it should have done this anyway.
8779 if (!g_key_file_has_group(key_file, "ServiceChanged")) {
8781 *ccc_le = device->le_state.bonded ? 0x0002 : 0x0000;
8783 *ccc_bredr = device->bredr_state.bonded ?
8785 g_key_file_free(key_file);
8790 *ccc_le = g_key_file_get_integer(key_file, "ServiceChanged",
8794 *ccc_bredr = g_key_file_get_integer(key_file, "ServiceChanged",
8795 "CCC_BR/EDR", NULL);
8797 g_key_file_free(key_file);
8800 void device_set_rssi_with_delta(struct btd_device *device, int8_t rssi,
8801 int8_t delta_threshold)
8806 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8807 if (rssi == 0 || device->rssi == 0) {
8808 if (device->rssi == rssi)
8812 device->rssi = rssi;
8813 DBG("rssi %d", rssi);
8815 if (rssi == 0 || device->rssi == 0) {
8816 if (device->rssi == rssi)
8819 DBG("rssi %d", rssi);
8821 device->rssi = rssi;
8825 if (device->rssi > rssi)
8826 delta = device->rssi - rssi;
8828 delta = rssi - device->rssi;
8830 /* only report changes of delta_threshold dBm or more */
8831 if (delta < delta_threshold)
8834 DBG("rssi %d delta %d", rssi, delta);
8836 device->rssi = rssi;
8840 g_dbus_emit_property_changed(dbus_conn, device->path,
8841 DEVICE_INTERFACE, "RSSI");
8844 void device_set_rssi(struct btd_device *device, int8_t rssi)
8846 device_set_rssi_with_delta(device, rssi, RSSI_THRESHOLD);
8849 void device_set_tx_power(struct btd_device *device, int8_t tx_power)
8854 if (device->tx_power == tx_power)
8857 DBG("tx_power %d", tx_power);
8859 device->tx_power = tx_power;
8861 g_dbus_emit_property_changed(dbus_conn, device->path,
8862 DEVICE_INTERFACE, "TxPower");
8865 void device_set_flags(struct btd_device *device, uint8_t flags)
8870 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
8871 DBG("flags %d", flags);
8874 if (device->ad_flags[0] == flags)
8877 device->ad_flags[0] = flags;
8879 g_dbus_emit_property_changed(dbus_conn, device->path,
8880 DEVICE_INTERFACE, "AdvertisingFlags");
8883 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8884 void device_set_le_connectable(struct btd_device *device, uint8_t adv_type)
8889 if (device->le_connectable)
8892 if (adv_type == ADV_TYPE_IND || adv_type == ADV_TYPE_DIRECT_IND)
8893 device->le_connectable = true;
8897 bool device_is_connectable(struct btd_device *device)
8905 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8906 /* Check the ADV type. Some beacon device can be connectable regardless adv flags */
8907 return device->le_connectable;
8909 /* Check if either Limited or General discoverable are set */
8910 return (device->ad_flags[0] & 0x03);
8914 static gboolean start_discovery(gpointer user_data)
8916 struct btd_device *device = user_data;
8919 device_browse_sdp(device, NULL);
8921 device_browse_gatt(device, NULL);
8923 device->discov_timer = 0;
8928 void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type)
8930 struct bearer_state *state = get_state(dev, bdaddr_type);
8935 state->paired = true;
8937 /* If the other bearer state was already true we don't need to
8938 * send any property signals.
8940 if (dev->bredr_state.paired == dev->le_state.paired)
8943 if (!state->svc_resolved) {
8944 dev->pending_paired = true;
8948 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
8949 if (dev->bonding == NULL)
8951 g_dbus_emit_property_changed(dbus_conn, dev->path,
8952 DEVICE_INTERFACE, "Paired");
8955 void device_set_unpaired(struct btd_device *dev, uint8_t bdaddr_type)
8957 struct bearer_state *state = get_state(dev, bdaddr_type);
8962 state->paired = false;
8965 * If the other bearer state is still true we don't need to
8966 * send any property signals or remove device.
8968 if (dev->bredr_state.paired != dev->le_state.paired) {
8969 /* TODO disconnect only unpaired bearer */
8970 if (state->connected)
8971 device_request_disconnect(dev, NULL);
8976 g_dbus_emit_property_changed(dbus_conn, dev->path,
8977 DEVICE_INTERFACE, "Paired");
8979 btd_device_set_temporary(dev, true);
8981 if (btd_device_is_connected(dev))
8982 device_request_disconnect(dev, NULL);
8984 btd_adapter_remove_device(dev->adapter, dev);
8987 static void device_auth_req_free(struct btd_device *device)
8989 struct authentication_req *authr = device->authr;
8995 agent_unref(authr->agent);
8997 g_free(authr->pincode);
9000 device->authr = NULL;
9003 bool device_is_retrying(struct btd_device *device)
9005 struct bonding_req *bonding = device->bonding;
9007 return bonding && bonding->retry_timer > 0;
9010 void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
9013 struct bonding_req *bonding = device->bonding;
9014 struct authentication_req *auth = device->authr;
9015 struct bearer_state *state = get_state(device, bdaddr_type);
9017 DBG("bonding %p status 0x%02x", bonding, status);
9019 if (auth && auth->agent)
9020 agent_cancel(auth->agent);
9023 device_cancel_authentication(device, TRUE);
9024 device_bonding_failed(device, status);
9025 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9026 device->legacy_pairing = false;
9030 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9031 device->legacy_pairing = false;
9033 device_auth_req_free(device);
9035 /* If we're already paired nothing more is needed */
9036 if (state->paired) {
9037 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9038 if (bdaddr_type == BDADDR_BREDR && state->svc_resolved) {
9039 DBG("Link key has been changed. Report it");
9041 g_dbus_emit_property_changed(dbus_conn,
9042 device->path, DEVICE_INTERFACE,
9045 DBG("Just overwrite Link key");
9046 } else if (bdaddr_type == BDADDR_LE_RANDOM ||
9047 bdaddr_type == BDADDR_LE_PUBLIC) {
9048 DBG("Long Term Key has been changed. Report it");
9049 g_dbus_emit_property_changed(dbus_conn, device->path,
9050 DEVICE_INTERFACE, "Paired");
9052 #endif /* TIZEN_FEATURE_BLUEZ_MODIFY */
9056 device_set_paired(device, bdaddr_type);
9058 /* If services are already resolved just reply to the pairing
9061 if (state->svc_resolved && bonding) {
9062 /* Attept to store services for this device failed because it
9063 * was not paired. Now that we're paired retry. */
9064 store_gatt_db(device);
9066 g_dbus_send_reply(dbus_conn, bonding->msg, DBUS_TYPE_INVALID);
9067 bonding_request_free(bonding);
9071 /* If we were initiators start service discovery immediately.
9072 * However if the other end was the initator wait a few seconds
9073 * before SDP. This is due to potential IOP issues if the other
9074 * end starts doing SDP at the same time as us */
9076 DBG("Proceeding with service discovery");
9077 /* If we are initiators remove any discovery timer and just
9078 * start discovering services directly */
9079 if (device->discov_timer) {
9080 g_source_remove(device->discov_timer);
9081 device->discov_timer = 0;
9084 if (bdaddr_type == BDADDR_BREDR)
9085 device_browse_sdp(device, bonding->msg);
9087 device_browse_gatt(device, bonding->msg);
9089 bonding_request_free(bonding);
9090 } else if (!state->svc_resolved) {
9091 if (!device->browse && !device->discov_timer &&
9092 main_opts.reverse_discovery) {
9093 /* If we are not initiators and there is no currently
9094 * active discovery or discovery timer, set discovery
9096 DBG("setting timer for reverse service discovery");
9097 device->discov_timer = g_timeout_add_seconds(
9105 static gboolean svc_idle_cb(gpointer user_data)
9107 struct svc_callback *cb = user_data;
9108 struct btd_device *dev = cb->dev;
9110 dev->svc_callbacks = g_slist_remove(dev->svc_callbacks, cb);
9112 cb->func(cb->dev, 0, cb->user_data);
9119 unsigned int device_wait_for_svc_complete(struct btd_device *dev,
9120 device_svc_cb_t func,
9123 /* This API is only used for BR/EDR (for now) */
9124 struct bearer_state *state = &dev->bredr_state;
9125 static unsigned int id = 0;
9126 struct svc_callback *cb;
9128 cb = g_new0(struct svc_callback, 1);
9130 cb->user_data = user_data;
9134 dev->svc_callbacks = g_slist_prepend(dev->svc_callbacks, cb);
9136 if (state->svc_resolved || !main_opts.reverse_discovery)
9137 cb->idle_id = g_idle_add(svc_idle_cb, cb);
9138 else if (dev->discov_timer > 0) {
9139 g_source_remove(dev->discov_timer);
9140 dev->discov_timer = g_idle_add(start_discovery, dev);
9142 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9143 else if (!dev->browse) {
9144 DBG("Service is not going on. Start discovery");
9145 dev->discov_timer = g_idle_add(start_discovery, dev);
9147 DBG("Wait for service discovery");
9153 bool device_remove_svc_complete_callback(struct btd_device *dev,
9158 for (l = dev->svc_callbacks; l != NULL; l = g_slist_next(l)) {
9159 struct svc_callback *cb = l->data;
9164 if (cb->idle_id > 0)
9165 g_source_remove(cb->idle_id);
9167 dev->svc_callbacks = g_slist_remove(dev->svc_callbacks, cb);
9176 gboolean device_is_bonding(struct btd_device *device, const char *sender)
9178 struct bonding_req *bonding = device->bonding;
9180 if (!device->bonding)
9186 return g_str_equal(sender, dbus_message_get_sender(bonding->msg));
9189 static gboolean device_bonding_retry(gpointer data)
9191 struct btd_device *device = data;
9192 struct btd_adapter *adapter = device_get_adapter(device);
9193 struct bonding_req *bonding = device->bonding;
9200 DBG("retrying bonding");
9201 bonding->retry_timer = 0;
9203 /* Restart the bonding timer to the begining of the pairing. If not
9204 * pincode request/reply occurs during this retry,
9205 * device_bonding_last_duration() will return a consistent value from
9207 device_bonding_restart_timer(device);
9210 io_cap = agent_get_io_capability(bonding->agent);
9212 io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
9214 err = adapter_bonding_attempt(adapter, &device->bdaddr,
9215 device->bdaddr_type, io_cap);
9217 device_bonding_complete(device, bonding->bdaddr_type,
9223 int device_bonding_attempt_retry(struct btd_device *device)
9225 struct bonding_req *bonding = device->bonding;
9227 /* Ignore other failure events while retrying */
9228 if (device_is_retrying(device))
9234 /* Mark the end of a bonding attempt to compute the delta for the
9236 bonding_request_stop_timer(bonding);
9238 if (btd_adapter_pin_cb_iter_end(bonding->cb_iter))
9241 DBG("scheduling retry");
9242 bonding->retry_timer = g_timeout_add(3000,
9243 device_bonding_retry, device);
9247 void device_bonding_failed(struct btd_device *device, uint8_t status)
9249 struct bonding_req *bonding = device->bonding;
9252 DBG("status %u", status);
9255 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9256 if (device->legacy_pairing) {
9257 DBG("Emit LegacyPaired");
9258 g_dbus_emit_property_changed(dbus_conn, device->path,
9259 DEVICE_INTERFACE, "LegacyPaired");
9264 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9265 btd_device_set_temporary(device, TRUE);
9269 device_cancel_authentication(device, FALSE);
9271 reply = new_authentication_return(bonding->msg, status);
9272 g_dbus_send_message(dbus_conn, reply);
9274 bonding_request_free(bonding);
9277 struct btd_adapter_pin_cb_iter *device_bonding_iter(struct btd_device *device)
9279 if (device->bonding == NULL)
9282 return device->bonding->cb_iter;
9285 static void pincode_cb(struct agent *agent, DBusError *err, const char *pin,
9288 struct authentication_req *auth = data;
9289 struct btd_device *device = auth->device;
9291 /* No need to reply anything if the authentication already failed */
9292 if (auth->agent == NULL)
9295 btd_adapter_pincode_reply(device->adapter, &device->bdaddr,
9296 pin, pin ? strlen(pin) : 0);
9298 agent_unref(device->authr->agent);
9299 device->authr->agent = NULL;
9302 static void confirm_cb(struct agent *agent, DBusError *err, void *data)
9304 struct authentication_req *auth = data;
9305 struct btd_device *device = auth->device;
9307 /* No need to reply anything if the authentication already failed */
9308 if (auth->agent == NULL)
9311 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9312 btd_adapter_confirm_reply(device->adapter, &device->bdaddr,
9314 err ? FALSE : TRUE);
9315 device_set_auth_addr_type(device, BDADDR_BREDR);
9317 btd_adapter_confirm_reply(device->adapter, &device->bdaddr,
9319 err ? FALSE : TRUE);
9322 agent_unref(device->authr->agent);
9323 device->authr->agent = NULL;
9326 static void passkey_cb(struct agent *agent, DBusError *err,
9327 uint32_t passkey, void *data)
9329 struct authentication_req *auth = data;
9330 struct btd_device *device = auth->device;
9332 /* No need to reply anything if the authentication already failed */
9333 if (auth->agent == NULL)
9337 passkey = INVALID_PASSKEY;
9339 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9340 btd_adapter_passkey_reply(device->adapter, &device->bdaddr,
9341 auth->addr_type, passkey);
9342 device_set_auth_addr_type(device, BDADDR_BREDR);
9344 btd_adapter_passkey_reply(device->adapter, &device->bdaddr,
9345 auth->addr_type, passkey);
9348 agent_unref(device->authr->agent);
9349 device->authr->agent = NULL;
9352 static void display_pincode_cb(struct agent *agent, DBusError *err, void *data)
9354 struct authentication_req *auth = data;
9355 struct btd_device *device = auth->device;
9357 pincode_cb(agent, err, auth->pincode, auth);
9359 g_free(device->authr->pincode);
9360 device->authr->pincode = NULL;
9363 static struct authentication_req *new_auth(struct btd_device *device,
9368 struct authentication_req *auth;
9369 struct agent *agent;
9372 ba2str(&device->bdaddr, addr);
9373 DBG("Requesting agent authentication for %s", addr);
9375 if (device->authr) {
9376 error("Authentication already requested for %s", addr);
9380 if (device->bonding && device->bonding->agent)
9381 agent = agent_ref(device->bonding->agent);
9383 agent = agent_get(NULL);
9386 error("No agent available for request type %d", type);
9390 auth = g_new0(struct authentication_req, 1);
9391 auth->agent = agent;
9392 auth->device = device;
9394 auth->addr_type = addr_type;
9395 auth->secure = secure;
9396 device->authr = auth;
9401 int device_request_pincode(struct btd_device *device, gboolean secure)
9403 struct authentication_req *auth;
9406 auth = new_auth(device, BDADDR_BREDR, AUTH_TYPE_PINCODE, secure);
9410 err = agent_request_pincode(auth->agent, device, pincode_cb, secure,
9413 error("Failed requesting authentication");
9414 device_auth_req_free(device);
9420 int device_request_passkey(struct btd_device *device, uint8_t type)
9422 struct authentication_req *auth;
9425 auth = new_auth(device, type, AUTH_TYPE_PASSKEY, FALSE);
9429 err = agent_request_passkey(auth->agent, device, passkey_cb, auth,
9432 error("Failed requesting authentication");
9433 device_auth_req_free(device);
9439 int device_confirm_passkey(struct btd_device *device, uint8_t type,
9440 int32_t passkey, uint8_t confirm_hint)
9442 struct authentication_req *auth;
9445 auth = new_auth(device, type, AUTH_TYPE_CONFIRM, FALSE);
9449 auth->passkey = passkey;
9451 #ifndef TIZEN_FEATURE_BLUEZ_CONFIRM_ONLY
9453 err = agent_request_authorization(auth->agent, device,
9454 confirm_cb, auth, NULL);
9457 err = agent_request_confirmation(auth->agent, device, passkey,
9458 confirm_cb, auth, NULL);
9461 error("Failed requesting authentication");
9462 device_auth_req_free(device);
9468 int device_notify_passkey(struct btd_device *device, uint8_t type,
9469 uint32_t passkey, uint8_t entered)
9471 struct authentication_req *auth;
9474 if (device->authr) {
9475 auth = device->authr;
9476 if (auth->type != AUTH_TYPE_NOTIFY_PASSKEY)
9479 auth = new_auth(device, type, AUTH_TYPE_NOTIFY_PASSKEY, FALSE);
9484 err = agent_display_passkey(auth->agent, device, passkey, entered);
9486 error("Failed requesting authentication");
9487 device_auth_req_free(device);
9493 int device_notify_pincode(struct btd_device *device, gboolean secure,
9494 const char *pincode)
9496 struct authentication_req *auth;
9499 auth = new_auth(device, BDADDR_BREDR, AUTH_TYPE_NOTIFY_PINCODE, secure);
9503 auth->pincode = g_strdup(pincode);
9505 err = agent_display_pincode(auth->agent, device, pincode,
9506 display_pincode_cb, auth, NULL);
9508 error("Failed requesting authentication");
9509 device_auth_req_free(device);
9515 static void cancel_authentication(struct authentication_req *auth)
9517 struct agent *agent;
9520 if (!auth || !auth->agent)
9523 agent = auth->agent;
9526 dbus_error_init(&err);
9527 dbus_set_error_const(&err, ERROR_INTERFACE ".Canceled", NULL);
9529 switch (auth->type) {
9530 case AUTH_TYPE_PINCODE:
9531 pincode_cb(agent, &err, NULL, auth);
9533 case AUTH_TYPE_CONFIRM:
9534 confirm_cb(agent, &err, auth);
9536 case AUTH_TYPE_PASSKEY:
9537 passkey_cb(agent, &err, 0, auth);
9539 case AUTH_TYPE_NOTIFY_PASSKEY:
9540 /* User Notify doesn't require any reply */
9542 case AUTH_TYPE_NOTIFY_PINCODE:
9543 pincode_cb(agent, &err, NULL, auth);
9547 dbus_error_free(&err);
9550 void device_cancel_authentication(struct btd_device *device, gboolean aborted)
9552 struct authentication_req *auth = device->authr;
9558 ba2str(&device->bdaddr, addr);
9559 DBG("Canceling authentication request for %s", addr);
9562 agent_cancel(auth->agent);
9565 cancel_authentication(auth);
9567 device_auth_req_free(device);
9569 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9570 device_set_auth_addr_type(device, BDADDR_BREDR);
9574 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9575 gboolean device_is_authenticating(struct btd_device *dev, uint8_t bdaddr_type)
9577 return (dev->auth_bdaddr_type == bdaddr_type && dev->authr != NULL);
9580 gboolean device_is_authenticating(struct btd_device *device)
9582 return (device->authr != NULL);
9586 struct gatt_primary *btd_device_get_primary(struct btd_device *device,
9591 match = g_slist_find_custom(device->primaries, uuid, bt_uuid_strcmp);
9598 GSList *btd_device_get_primaries(struct btd_device *device)
9600 return device->primaries;
9603 struct gatt_db *btd_device_get_gatt_db(struct btd_device *device)
9611 struct bt_gatt_client *btd_device_get_gatt_client(struct btd_device *device)
9616 return device->client;
9619 void *btd_device_get_attrib(struct btd_device *device)
9624 return device->attrib;
9627 struct bt_gatt_server *btd_device_get_gatt_server(struct btd_device *device)
9632 return device->server;
9635 void btd_device_gatt_set_service_changed(struct btd_device *device,
9636 uint16_t start, uint16_t end)
9639 * TODO: Remove this function and handle service changed via
9644 void btd_device_add_uuid(struct btd_device *device, const char *uuid)
9649 if (g_slist_find_custom(device->uuids, uuid, bt_uuid_strcmp))
9652 new_uuid = g_strdup(uuid);
9653 uuid_list = g_slist_append(NULL, new_uuid);
9655 device_probe_profiles(device, uuid_list);
9658 g_slist_free(uuid_list);
9660 store_device_info(device);
9662 g_dbus_emit_property_changed(dbus_conn, device->path,
9663 DEVICE_INTERFACE, "UUIDs");
9666 static sdp_list_t *read_device_records(struct btd_device *device)
9668 char local[18], peer[18];
9669 char filename[PATH_MAX];
9671 char **keys, **handle;
9673 sdp_list_t *recs = NULL;
9676 ba2str(btd_adapter_get_address(device->adapter), local);
9677 ba2str(&device->bdaddr, peer);
9679 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9681 ba2str(device->rpa, peer);
9684 snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
9686 key_file = g_key_file_new();
9687 g_key_file_load_from_file(key_file, filename, 0, NULL);
9688 keys = g_key_file_get_keys(key_file, "ServiceRecords", NULL, NULL);
9690 for (handle = keys; handle && *handle; handle++) {
9691 str = g_key_file_get_string(key_file, "ServiceRecords",
9696 rec = record_from_string(str);
9697 recs = sdp_list_append(recs, rec);
9702 g_key_file_free(key_file);
9707 void btd_device_set_record(struct btd_device *device, const char *uuid,
9710 /* This API is only used for BR/EDR */
9711 struct bearer_state *state = &device->bredr_state;
9712 struct browse_req *req;
9713 sdp_list_t *recs = NULL;
9719 req = browse_request_new(device, BROWSE_SDP, NULL);
9723 rec = record_from_string(record);
9724 recs = sdp_list_append(recs, rec);
9725 update_bredr_services(req, recs);
9726 sdp_list_free(recs, NULL);
9728 device->svc_refreshed = true;
9729 state->svc_resolved = true;
9731 device_probe_profiles(device, req->profiles_added);
9733 /* Propagate services changes */
9734 g_dbus_emit_property_changed(dbus_conn, req->device->path,
9735 DEVICE_INTERFACE, "UUIDs");
9737 device_svc_resolved(device, BROWSE_SDP, device->bdaddr_type, 0);
9740 const sdp_record_t *btd_device_get_record(struct btd_device *device,
9743 /* Load records from storage if there is nothing in cache */
9744 if (!device->tmp_records) {
9745 device->tmp_records = read_device_records(device);
9746 if (!device->tmp_records)
9750 return find_record_in_list(device->tmp_records, uuid);
9753 struct btd_device *btd_device_ref(struct btd_device *device)
9755 __sync_fetch_and_add(&device->ref_count, 1);
9760 void btd_device_unref(struct btd_device *device)
9762 if (__sync_sub_and_fetch(&device->ref_count, 1))
9765 if (!device->path) {
9766 error("freeing device without an object path");
9770 DBG("Freeing device %s", device->path);
9772 g_dbus_unregister_interface(dbus_conn, device->path, DEVICE_INTERFACE);
9775 int device_get_appearance(struct btd_device *device, uint16_t *value)
9777 if (device->appearance == 0)
9781 *value = device->appearance;
9786 void device_set_appearance(struct btd_device *device, uint16_t value)
9788 const char *icon = gap_appearance_to_icon(value);
9790 if (device->appearance == value)
9793 g_dbus_emit_property_changed(dbus_conn, device->path,
9794 DEVICE_INTERFACE, "Appearance");
9797 g_dbus_emit_property_changed(dbus_conn, device->path,
9798 DEVICE_INTERFACE, "Icon");
9800 device->appearance = value;
9801 store_device_info(device);
9804 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9805 int device_get_rpa_res_char_value(struct btd_device *device)
9807 return device->rpa_res_support;
9810 /* Store the RPA Resolution Characteristic Value of remote device.
9811 * This value would be checked before start directed advertising using RPA.
9813 void device_set_rpa_res_char_value(struct btd_device *device, uint8_t value)
9815 if (device->rpa_res_support == value)
9818 device->rpa_res_support = value;
9819 store_device_info(device);
9822 void device_set_manufacturer_info(struct btd_device *device, struct eir_data *eir)
9827 if (eir->manufacturer_data_len == 0)
9830 device->manufacturer_data = g_memdup(eir->manufacturer_data,
9831 eir->manufacturer_data_len);
9832 device->manufacturer_data_len = eir->manufacturer_data_len;
9834 store_device_info(device);
9836 g_dbus_emit_property_changed(dbus_conn, device->path,
9837 DEVICE_INTERFACE, "LegacyManufacturerDataLen");
9839 g_dbus_emit_property_changed(dbus_conn, device->path,
9840 DEVICE_INTERFACE, "LegacyManufacturerData");
9844 void device_set_adv_report_info(struct btd_device *device, void *data, uint8_t data_len,
9845 uint8_t adv_type, int8_t rssi)
9851 const char *paddr = peer_addr;
9852 dbus_int32_t rssi_val = rssi;
9853 int adv_len = data_len;
9856 ba2str(&device->bdaddr, peer_addr);
9858 /* Replace address type for paired RPA device since IDA passed from controller */
9860 ba2str(device->rpa, peer_addr);
9861 addr_type = BDADDR_LE_RANDOM;
9863 addr_type = device->bdaddr_type;
9865 g_dbus_emit_signal(dbus_conn, device->path,
9866 DEVICE_INTERFACE, "AdvReport",
9867 DBUS_TYPE_STRING, &paddr,
9868 DBUS_TYPE_BYTE, &addr_type,
9869 DBUS_TYPE_BYTE, &adv_type,
9870 DBUS_TYPE_INT32, &rssi_val,
9871 DBUS_TYPE_INT32, &adv_len,
9872 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_len,
9876 void device_set_payload_timeout(struct btd_device *device,
9877 uint16_t payload_timeout)
9881 if (device->auth_payload_timeout == payload_timeout)
9884 DBG("Payload timeout %d", payload_timeout);
9886 device->auth_payload_timeout = payload_timeout;
9887 g_dbus_emit_property_changed(dbus_conn, device->path,
9888 DEVICE_INTERFACE, "PayloadTimeout");
9891 void device_set_disconnect_reason(struct btd_device *device, uint8_t reason)
9893 device->disc_reason = reason;
9896 void btd_device_disconnect(struct btd_device *device)
9899 struct btd_service *service;
9900 btd_service_state_t state;
9902 ba2str(&device->bdaddr, dst);
9905 if (device->bredr_state.connected == false)
9908 service = btd_device_get_service(device, HFP_HS_UUID);
9912 state = btd_service_get_state(service);
9913 DBG("Connected State : %d", state);
9915 if (state == BTD_SERVICE_STATE_DISCONNECTED) {
9916 btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
9925 void btd_device_set_pnpid(struct btd_device *device, uint16_t source,
9926 uint16_t vendor, uint16_t product, uint16_t version)
9928 if (device->vendor_src == source && device->version == version &&
9929 device->vendor == vendor && device->product == product)
9932 device->vendor_src = source;
9933 device->vendor = vendor;
9934 device->product = product;
9935 device->version = version;
9937 free(device->modalias);
9938 device->modalias = bt_modalias(source, vendor, product, version);
9940 g_dbus_emit_property_changed(dbus_conn, device->path,
9941 DEVICE_INTERFACE, "Modalias");
9943 store_device_info(device);
9946 static void service_state_changed(struct btd_service *service,
9947 btd_service_state_t old_state,
9948 btd_service_state_t new_state,
9951 struct btd_profile *profile = btd_service_get_profile(service);
9952 struct btd_device *device = btd_service_get_device(service);
9953 int err = btd_service_get_error(service);
9955 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
9957 if (old_state == BTD_SERVICE_STATE_UNAVAILABLE ||
9958 new_state == BTD_SERVICE_STATE_UNAVAILABLE)
9959 DBG("Skip status updating ([%d] -> [%d])", old_state, new_state);
9961 g_dbus_emit_signal(dbus_conn, device->path,
9962 DEVICE_INTERFACE, "ProfileStateChanged",
9963 DBUS_TYPE_STRING, &profile->remote_uuid,
9964 DBUS_TYPE_INT32, &new_state,
9968 if (new_state == BTD_SERVICE_STATE_CONNECTING ||
9969 new_state == BTD_SERVICE_STATE_DISCONNECTING ||
9970 new_state == BTD_SERVICE_STATE_UNAVAILABLE)
9972 if (new_state == BTD_SERVICE_STATE_CONNECTING ||
9973 new_state == BTD_SERVICE_STATE_DISCONNECTING)
9977 if (old_state == BTD_SERVICE_STATE_CONNECTING)
9978 device_profile_connected(device, profile, err);
9979 else if (old_state == BTD_SERVICE_STATE_DISCONNECTING)
9980 device_profile_disconnected(device, profile, err);
9983 struct btd_service *btd_device_get_service(struct btd_device *dev,
9984 const char *remote_uuid)
9988 for (l = dev->services; l != NULL; l = g_slist_next(l)) {
9989 struct btd_service *service = l->data;
9990 struct btd_profile *p = btd_service_get_profile(service);
9992 if (g_str_equal(p->remote_uuid, remote_uuid))
9995 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
9996 if (g_str_equal(HID_UUID, remote_uuid)) {
9997 if (strcmp(p->name, "hid-device") == 0)
10006 void btd_device_init(void)
10008 dbus_conn = btd_get_dbus_connection();
10009 service_state_cb_id = btd_service_add_state_cb(
10010 service_state_changed, NULL);
10013 void btd_device_cleanup(void)
10015 btd_service_remove_state_cb(service_state_cb_id);
10018 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
10019 void btd_device_set_legacy_pairing(struct btd_device *dev, bool legacy_pairing)
10021 dev->legacy_pairing = legacy_pairing;
10024 void btd_device_set_svc_changed_indication(struct btd_device *dev, bool value)
10026 bt_att_set_svc_changed_indication_registered(dev->att, value);
10027 store_device_info(dev);
10030 bool btd_device_get_svc_changed_indication(struct btd_device *dev)
10032 return bt_att_get_svc_changed_indication_registered(dev->att);