4 * Copyright (c) 2015 -2016 Samsung Electronics Co., Ltd All Rights Reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
27 #include <dbus/dbus-glib.h>
28 #include <dbus/dbus.h>
34 #include <syspopup_caller.h>
35 #include <bundle_internal.h>
39 #include "bt-hal-log.h"
40 #include "bt-hal-msg.h"
41 #include "bt-hal-internal.h"
42 #include "bt-hal-event-receiver.h"
43 #include "bt-hal-dbus-common-utils.h"
45 #include "bt-hal-adapter-dbus-handler.h"
46 #include "bt-hal-device-dbus-handler.h"
47 #include "bt-hal-event-receiver.h"
48 #include "bt-hal-agent.h"
50 static handle_stack_msg event_cb = NULL;
52 /* Forward Delcaration */
53 static void __bt_hal_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data);
55 static void __bt_hal_unbond_device_cb(GDBusProxy *proxy, GAsyncResult *res,
58 int _bt_hal_device_create_bond(const bt_bdaddr_t *bd_addr)
61 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
64 GDBusConnection *conn;
65 char *device_path = NULL;
66 GDBusProxy *adapter_proxy;
68 struct hal_ev_bond_state_changed ev;
69 memset(&ev, 0, sizeof(ev));
72 DBG("Transport [%d] Add[0x%x] [0x%x][0x%x][0x%x][0x%x][0x%x]",
73 transport, bd_addr->address[0], bd_addr->address[1],
74 bd_addr->address[2], bd_addr->address[3],
75 bd_addr->address[4], bd_addr->address[5]);
76 conn = _bt_get_system_gconn();
78 DBG("Could not get DBUS connection!");
79 return BT_STATUS_FAIL;
82 _bt_convert_addr_type_to_string(address, bd_addr->address);
83 device_path = _bt_get_device_object_path(address);
85 if (device_path == NULL) {
86 ERR("No searched device, attempt to create device");
88 adapter_proxy = _bt_get_adapter_proxy();
90 ERR("Could not get Adapter Proxy");
91 return BT_STATUS_FAIL;
94 ret = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
95 g_variant_new("(s)", address),
96 G_DBUS_CALL_FLAGS_NONE,
102 ERR("CreateDevice Fail: %s", error->message);
103 g_clear_error(&error);
106 g_variant_unref(ret);
107 device_path = _bt_get_device_object_path(address);
109 if (device_path == NULL) {
110 ERR("Device path is still not created!!");
111 return BT_STATUS_FAIL;
113 DBG("Device_path is created[%s]", device_path);
116 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
117 NULL, BT_HAL_BLUEZ_NAME,
118 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
122 ERR("Could not get Device Proxy");
123 return BT_STATUS_FAIL;
126 g_dbus_proxy_call(proxy, "Pair",
127 g_variant_new("(y)", transport),
128 G_DBUS_CALL_FLAGS_NONE,
129 BT_HAL_MAX_DBUS_TIMEOUT,
131 (GAsyncReadyCallback)__bt_hal_bond_device_cb,
134 /* Prepare to send Bonding event event to HAL bluetooth */
135 ev.status = BT_STATUS_SUCCESS;
136 ev.state = BT_BOND_STATE_BONDING;
138 _bt_convert_addr_string_to_type(ev.bdaddr, address);
141 event_cb = _bt_hal_get_stack_message_handler();
143 DBG("Sending HAL_EV_BOND_STATE_CHANGED event");
144 event_cb(HAL_EV_BOND_STATE_CHANGED, (void*)&ev, sizeof(ev));
148 return BT_STATUS_SUCCESS;
151 int _bt_hal_device_remove_bond(const bt_bdaddr_t *bd_addr)
153 char *device_path = NULL;
154 GDBusProxy *adapter_proxy = NULL;
155 GDBusProxy *device_proxy = NULL;
156 GDBusConnection *conn;
157 GError *error = NULL;
158 GVariant *ret = NULL;
159 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
161 DBG("Add[0x%x] [0x%x][0x%x][0x%x][0x%x][0x%x]",
162 bd_addr->address[0], bd_addr->address[1],
163 bd_addr->address[2], bd_addr->address[3],
164 bd_addr->address[4], bd_addr->address[5]);
166 adapter_proxy = _bt_get_adapter_proxy();
167 if (!adapter_proxy) {
168 ERR("Could not get Adapter Proxy");
169 return BT_STATUS_FAIL;
172 _bt_convert_addr_type_to_string(address, bd_addr->address);
174 device_path = _bt_get_device_object_path(address);
176 /* This is a special case, bluedroid always sends success to HAL even if device is already removed
177 whereas bluez sends BLUETOOTH_ERROR_NOT_PAIRED. However we will return Failure
179 if (device_path == NULL) {
180 ERR("No paired device");
181 return BT_STATUS_FAIL;
184 conn = _bt_get_system_gconn();
187 return BT_STATUS_FAIL;
191 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
192 NULL, BT_HAL_BLUEZ_NAME,
193 device_path, BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
195 if (device_proxy != NULL) {
197 ret = g_dbus_proxy_call_sync(device_proxy, "Get",
198 g_variant_new("(ss)", BT_HAL_DEVICE_INTERFACE, "Paired"),
199 G_DBUS_CALL_FLAGS_NONE,
204 ERR("Getting property failed: [%s]\n", error->message);
206 return BT_STATUS_FAIL;
209 ERR("No paired device");
210 g_object_unref(device_proxy);
211 return BT_STATUS_FAIL;
213 g_variant_unref(ret);
215 g_object_unref(device_proxy);
218 g_dbus_proxy_call(adapter_proxy, "UnpairDevice",
219 g_variant_new("(o)", device_path),
220 G_DBUS_CALL_FLAGS_NONE,
221 BT_HAL_MAX_DBUS_TIMEOUT,
223 (GAsyncReadyCallback)__bt_hal_unbond_device_cb,
224 (gpointer)device_path);
227 return BT_STATUS_SUCCESS;
230 static void __bt_hal_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res,
234 const char *device_path;
235 int result = BT_STATUS_SUCCESS;
236 struct hal_ev_bond_state_changed ev;
237 memset(&ev, 0, sizeof(ev));
238 char dev_address[18];
241 #ifdef TIZEN_SYSPOPUP_SUPPORTED
242 /* Terminate ALL system popup */
243 syspopup_destroy_all();
246 g_dbus_proxy_call_finish(proxy, res, &err);
247 device_path = g_dbus_proxy_get_object_path(proxy);
248 DBG("Device path: %s", device_path);
249 _bt_convert_device_path_to_address(device_path, dev_address);
250 DBG("Remote Device address [%s]", dev_address);
253 g_dbus_error_strip_remote_error(err);
254 ERR("@@@Error occured in CreateBonding [%s]", err->message);
255 if (g_strrstr(err->message, "Already Exists")) {
256 ERR("Still bond existing even after remove");
257 result = BT_STATUS_AUTH_FAILURE;
258 } else if (g_strrstr(err->message, "Authentication Rejected")) {
260 result = BT_STATUS_AUTH_REJECTED;
261 } else if (_bt_hal_agent_is_canceled() ||
262 g_strrstr(err->message, "Authentication Canceled")) {
263 INFO("Cancelled by USER");
264 result = BT_STATUS_AUTH_FAILURE;
265 } else if (g_strrstr(err->message, "In Progress")) {
266 INFO("Bond in progress, cancel and retry");
267 } else if (g_strrstr(err->message, "Authentication Failed")) {
268 INFO("Authentication Failed");
269 result = BT_STATUS_AUTH_FAILURE;
270 } else if (g_strrstr(err->message, "Page Timeout")) {
271 INFO("Page Timeout");
272 /* This is the special case
273 As soon as call bluetooth_bond_device, try to cancel bonding.
274 In this case, before completing to call 'CreatePairedDevice' method
275 the procedure is stopped. So 'Cancle' error is not return.
277 result = BT_STATUS_RMT_DEV_DOWN;
278 } else if (g_strrstr(err->message, BT_HAL_TIMEOUT_MESSAGE)) {
280 result = BT_STATUS_FAIL;
281 } else if (g_strrstr(err->message, "Connection Timeout")) {
282 /* Pairing request timeout */
283 result = BT_STATUS_RMT_DEV_DOWN;
284 } else if (g_strrstr(err->message, "Authentication Timeout")) {
285 /* Pairing request timeout */
286 result = BT_STATUS_AUTH_FAILURE;
288 DBG("Default case: Pairing failed");
289 result = BT_STATUS_AUTH_FAILURE;
293 if (result == BT_STATUS_AUTH_FAILURE ||
294 result == BT_STATUS_RMT_DEV_DOWN ||
295 result == BT_STATUS_AUTH_REJECTED ||
296 result == BT_STATUS_FAIL) {
297 DBG("Bonding Failed!!");
299 DBG("Bonding Success!!");
302 /* Prepare to send event to HAL bluetooth */
304 if (result == BT_STATUS_SUCCESS)
305 ev.state = BT_BOND_STATE_BONDED;
307 ev.state = BT_BOND_STATE_NONE;
309 _bt_convert_addr_string_to_type(ev.bdaddr, dev_address);
312 event_cb = _bt_hal_get_stack_message_handler();
314 DBG("Sending HAL_EV_BOND_STATE_CHANGED event");
315 event_cb(HAL_EV_BOND_STATE_CHANGED, (void*)&ev, sizeof(ev));
320 static void __bt_hal_unbond_device_cb(GDBusProxy *proxy, GAsyncResult *res,
324 char *device_path = NULL;
325 char dev_address[18];
326 int result = BT_STATUS_SUCCESS;
327 struct hal_ev_bond_state_changed ev;
328 memset(&ev, 0, sizeof(ev));
331 g_dbus_proxy_call_finish(proxy, res, &err);
334 ERR("Error occured in RemoveBonding [%s]\n", err->message);
335 result = BT_STATUS_FAIL;
340 /* Prepare to send event to HAL bluetooth */
342 ev.state = BT_BOND_STATE_NONE;
344 device_path = (char *)user_data;
345 _bt_convert_device_path_to_address(device_path, dev_address);
346 _bt_convert_addr_string_to_type(ev.bdaddr, dev_address);
349 event_cb = _bt_hal_get_stack_message_handler();
351 DBG("Sending HAL_EV_BOND_STATE_CHANGED event");
352 event_cb(HAL_EV_BOND_STATE_CHANGED, (void*)&ev, sizeof(ev));
358 static gboolean __bt_device_bonded_device_info_cb(gpointer user_data)
360 /* Buffer and propety count management */
361 uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
362 struct hal_ev_remote_device_props *ev = (void*) buf;;
365 GVariant *result = user_data;
366 GVariantIter *property_iter;
367 GVariantIter *char_value_iter;
369 const gchar *address = NULL;
370 const gchar *name = NULL;
371 unsigned int cod = 0;
373 gboolean trust = FALSE;
374 gboolean paired = FALSE;
376 GByteArray *manufacturer_data = NULL;
380 unsigned int data_len = 0;
382 memset(buf, 0, sizeof(buf));
385 ev->status = BT_STATUS_SUCCESS;
387 g_variant_get(result, "(a{sv})", &property_iter);
388 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
389 if(!g_strcmp0(key, "Address")) {
390 address = g_variant_get_string(value, NULL);
391 DBG("Address [%s]", address);
392 _bt_convert_addr_string_to_type(ev->bdaddr, address);
393 } else if (!g_strcmp0(key, "Alias")) {
394 name = g_variant_get_string(value, NULL);
395 DBG("Alias [%s]", name);
396 size += __bt_insert_hal_properties(buf + size,
397 HAL_PROP_DEVICE_FRIENDLY_NAME, strlen(name) + 1, name);
399 } else if (!g_strcmp0(key, "Class")) {
400 cod = g_variant_get_uint32(value);
401 DBG("Class [%d]", cod);
402 size += __bt_insert_hal_properties(buf + size,
403 HAL_PROP_DEVICE_CLASS, sizeof(unsigned int), &cod);
405 } else if (!g_strcmp0(key, "Connected")) {
406 connected = g_variant_get_byte(value);
407 DBG("Connected [%d]", connected);
408 size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_CONNECTED,
409 sizeof(unsigned int), &connected);
411 } else if (!g_strcmp0(key,"Paired")) {
412 paired = g_variant_get_boolean(value);
413 DBG("Paired [%d]", paired);
414 size += __bt_insert_hal_properties(buf + size,
415 HAL_PROP_DEVICE_PAIRED, sizeof(unsigned int), &paired);
417 } else if (!g_strcmp0(key, "Trusted")) {
418 trust = g_variant_get_boolean(value);
419 DBG("Trusted [%d]", trust);
420 size += __bt_insert_hal_properties(buf + size,
421 HAL_PROP_DEVICE_TRUSTED, sizeof(unsigned int), &trust);
423 } else if (!g_strcmp0(key, "Name")) {
424 name = g_variant_get_string(value, NULL);
425 DBG("Name [%s]", name);
426 size += __bt_insert_hal_properties(buf + size,
427 HAL_PROP_DEVICE_NAME, strlen(name) + 1, name);
429 } else if (!g_strcmp0(key, "RSSI")) {
430 rssi = g_variant_get_int16(value);
431 DBG("RSSI [%d]", rssi);
432 size += __bt_insert_hal_properties(buf + size,
433 HAL_PROP_DEVICE_RSSI, sizeof(unsigned int), &rssi);
435 } else if (!g_strcmp0(key, "UUIDs")) {
440 size1 = g_variant_get_size(value);
441 int num_props_tmp = ev->num_props;
443 uuid_value = (char **)g_variant_get_strv(value, &size1);
444 for (i = 0; uuid_value[i] != NULL; i++)
446 /* UUID collection */
447 uint8_t uuids[BT_HAL_STACK_UUID_SIZE * uuid_count];
448 for (i = 0; uuid_value[i] != NULL; i++) {
449 char *uuid_str = NULL;
450 uint8_t uuid[BT_HAL_STACK_UUID_SIZE];
451 memset(uuid, 0x00, BT_HAL_STACK_UUID_SIZE);
452 uuid_str = g_strdup(uuid_value[i]);
453 DBG("UUID string [%s]\n", uuid_str);
454 _bt_convert_uuid_string_to_type(uuid, uuid_str);
455 memcpy(uuids + i * BT_HAL_STACK_UUID_SIZE, uuid, BT_HAL_STACK_UUID_SIZE);
457 size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_UUIDS,
458 (BT_HAL_STACK_UUID_SIZE * uuid_count), uuids);
459 ev->num_props = num_props_tmp + 1;
462 } else if (!g_strcmp0(key, "ManufacturerDataLen")) {
463 data_len = g_variant_get_uint16(value);
464 DBG("ManufacturerDataLen [%d]", data_len);
465 } else if (!g_strcmp0(key, "ManufacturerData")) {
466 manufacturer_data = g_byte_array_new();
467 g_variant_get(value, "ay", &char_value_iter);
468 while(g_variant_iter_loop(char_value_iter, "y", &char_value)) {
469 g_byte_array_append(manufacturer_data, &char_value, 1);
472 if (manufacturer_data) {
473 if (manufacturer_data->len > 0) {
474 size += __bt_insert_hal_properties(
475 buf + size, HAL_PROP_DEVICE_BLE_ADV_DATA,
476 manufacturer_data->len, manufacturer_data->data);
480 g_byte_array_free(manufacturer_data, FALSE);
482 ERR("Unhandled Property:[%s]", key);
486 DBG("trust: %d, paired: %d", trust, paired);
488 event_cb = _bt_hal_get_stack_message_handler();
490 ERR("event_cb is NULL");
494 if ((paired == FALSE) && (trust == FALSE)) {
495 ev->status = BT_STATUS_FAIL;
498 DBG("Send Remote Device properties event to HAL,"
499 " Num Prop [%d] total size [%d]",ev->num_props, size);
500 event_cb(HAL_EV_REMOTE_DEVICE_PROPS, (void*) buf, size);
503 DBG("Send Remote Device properties event to HAL,"
504 " Num Prop [%d] total size [%d]",ev->num_props, size);
505 event_cb(HAL_EV_REMOTE_DEVICE_PROPS, (void*) buf, size);
510 g_variant_unref(result);
514 int _bt_hal_dbus_get_remote_device_properties(bt_bdaddr_t *remote_addr)
516 char *device_path = NULL;
517 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
518 GError *error = NULL;
519 GDBusProxy *device_proxy;
520 GDBusConnection *conn;
524 ERR("Invalid device address ptr received");
525 return BT_STATUS_PARM_INVALID;
528 _bt_convert_addr_type_to_string(address, remote_addr->address);
529 device_path = _bt_get_device_object_path(address);
531 ERR("Device not paired");
532 return BT_STATUS_FAIL;
535 conn = _bt_get_system_gconn();
537 ERR("_bt_get_system_gconn failed");
538 return BT_STATUS_FAIL;
541 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
545 BT_HAL_PROPERTIES_INTERFACE,
549 ERR("Error creating device_proxy");
551 return BT_STATUS_FAIL;
554 result = g_dbus_proxy_call_sync(device_proxy,
556 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
557 G_DBUS_CALL_FLAGS_NONE,
563 ERR("Error occured in Proxy call");
565 ERR("Error occured in Proxy call (Error: %s)", error->message);
566 g_clear_error(&error);
568 g_object_unref(device_proxy);
570 return BT_STATUS_FAIL;
573 g_object_unref(device_proxy);
576 * As we need to provide async callback to user from HAL, simply schedule a
577 * callback method which will carry actual result
579 g_idle_add(__bt_device_bonded_device_info_cb, (gpointer)result);
582 return BT_STATUS_SUCCESS;
585 static int __bt_hal_dbus_set_remote_device_alias(bt_bdaddr_t *remote_addr, char *alias)
587 char address[BT_HAL_ADDRESS_STRING_SIZE];
588 gchar *device_path = NULL;
589 GDBusProxy *adapter_proxy;
590 GDBusProxy *device_proxy;
591 GError *error = NULL;
592 GDBusConnection *conn;
595 adapter_proxy = _bt_get_adapter_proxy();
596 if (!adapter_proxy) {
597 ERR("Could not get Adapter Proxy");
598 return BT_STATUS_FAIL;
601 conn = _bt_get_system_gconn();
603 ERR("_bt_get_system_gconn failed");
604 return BT_STATUS_FAIL;
607 _bt_convert_addr_type_to_string(address, remote_addr->address);
608 INFO("Address: %s, Alias: %s", address, alias);
610 device_path = _bt_get_device_object_path(address);
611 if (device_path == NULL) {
612 ERR("No paired device");
613 return BT_STATUS_FAIL;
616 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
617 NULL, BT_HAL_BLUEZ_NAME, device_path,
618 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
621 ERR("Error creating device_proxy");
622 return BT_STATUS_FAIL;
625 result = g_dbus_proxy_call_sync(device_proxy, "Set",
626 g_variant_new("(ssv)",
627 BT_HAL_DEVICE_INTERFACE,
628 "Alias", g_variant_new("s", alias)),
629 G_DBUS_CALL_FLAGS_NONE,
633 g_object_unref(device_proxy);
635 ERR("Error occured in Proxy call");
637 ERR("Error occured in Proxy call (Error: %s)", error->message);
638 g_clear_error(&error);
640 return BT_STATUS_FAIL;
642 g_variant_unref(result);
644 return BT_STATUS_SUCCESS;
647 /* Set Remote Device Properties */
648 int _bt_hal_dbus_set_remote_device_property(
649 bt_bdaddr_t *remote_addr, const bt_property_t *property)
655 if (remote_addr == NULL) {
656 ERR("Invalid parameters received");
657 return BT_STATUS_PARM_INVALID;
660 if (property == NULL || property->val == NULL) {
661 ERR("Invalid parameters received");
662 return BT_STATUS_PARM_INVALID;
665 switch (property->type) {
666 case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
667 result = __bt_hal_dbus_set_remote_device_alias(
668 remote_addr, (char *) property->val);
671 result = BT_STATUS_UNSUPPORTED;
674 DBG("Result= [%d]", result);