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.
29 #include <bundle_internal.h>
30 #include <eventsystem.h>
44 #include "bt-hal-log.h"
45 #include "bt-hal-msg.h"
46 #include "bt-hal-internal.h"
47 #include "bt-hal-utils.h"
48 #include "bt-hal-event-receiver.h"
49 #include "bt-hal-dbus-common-utils.h"
51 #include "bt-hal-adapter-dbus-handler.h"
52 #include "bt-hal-rfcomm-dbus-handler.h"
53 #include "bt-hal-event-receiver.h"
55 #include <bt-hal-agent.h>
56 #include <bt-hal-gap-agent.h>
57 #include <bt-hal-dbus-common-utils.h>
59 /* TODO_40 : 4.0 merge */
60 #include "bt-internal-types.h"
62 #define BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE (APP_SYSCONFDIR"/auto-pair-blacklist")
63 #define BT_HAL_AGENT_NEW_LINE "\r\n"
65 #define PAGE_SIZE (1 << 12)
66 #define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1)))
67 #define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
68 #define PAGE_ALIGN(addr) _ALIGN_DOWN(addr, PAGE_SIZE)
69 #define BT_HAL_PIN_MAX_LENGTH 16
70 #define BT_HAL_PASSKEY_MAX_LENGTH 4
71 #define BT_HAL_LOWER_ADDRESS_LENGTH 9
72 #define BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
73 #define BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT 3
75 #define G_VARIANT_UNREF(variant) \
76 g_variant_unref(variant); \
78 #define BT_HAL_MAX_EVENT_STR_LENGTH 50
80 static void *adapter_agent = NULL;
81 static gboolean passkey_display_notification = FALSE;
82 static gboolean passkey_confirm_notification = FALSE;
83 static gboolean passkey_notification = FALSE;
84 static gboolean pincode_notification = FALSE;
86 /* Forward delcaration */
87 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
89 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device);
90 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
92 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device);
93 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
95 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
97 static gboolean __bt_hal_authorize_cancel_request(GapAgentPrivate *agent, const char *address);
98 static gboolean __bt_hal_pairing_cancel_request(GapAgentPrivate *agent, const char *address);
99 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface);
100 static void __bt_hal_agent_release_memory(void);
101 static inline void stack_trim(void);
103 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class);
104 static gboolean __bt_hal_is_hid_device_connectable(void);
105 static int __bt_hal_device_generate_passkey(char *passkey, int size);
106 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
107 const gchar *address, const gchar *name);
108 static gboolean __bt_hal_device_is_device_blacklisted(const char *address, const char *name);
109 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
110 const char *address);
111 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
112 const char *partial_name);
113 static void __bt_hal_send_ssp_request_events(const gchar *address, const gchar *name,
114 guint passkey, uint32_t cod, unsigned char variant);
115 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid);
117 void* _bt_hal_create_agent(const char *path, gboolean adapter)
119 GAP_AGENT_FUNC_CB func_cb;
120 GDBusProxy *adapter_proxy;
121 GapAgentPrivate *agent;
124 adapter_proxy = _bt_hal_get_adapter_proxy();
128 func_cb.pincode_func = __bt_hal_pincode_request;
129 func_cb.display_func = __bt_hal_display_request;
130 func_cb.passkey_func = __bt_hal_passkey_request;
131 func_cb.confirm_func = __bt_hal_confirm_request;
132 func_cb.authorize_func = __bt_hal_authorize_request;
133 func_cb.pairing_cancel_func = __bt_hal_pairing_cancel_request;
134 func_cb.authorization_cancel_func = __bt_hal_authorize_cancel_request;
137 agent = g_new0(GapAgentPrivate, 1);
139 _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
142 if (!_gap_agent_register(agent)) {
143 ERR("gap agent registration failed!");
144 _bt_hal_destroy_agent(agent);
152 void _bt_hal_destroy_agent(void *agent)
158 _gap_agent_reset_dbus((GapAgentPrivate *)agent);
164 gboolean _bt_hal_agent_is_canceled(void)
166 void *agent = _bt_hal_get_adapter_agent();
170 return _gap_agent_is_canceled(agent);
173 int _bt_hal_agent_reply_cancellation(void)
175 void *agent = _bt_hal_get_adapter_agent();
177 return BT_STATUS_FAIL;
179 if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
180 ERR("Fail to reply agent");
181 return BT_STATUS_FAIL;
183 DBG("gap agent cancellation done successfully!");
184 return BT_STATUS_SUCCESS;
188 void _bt_hal_agent_set_canceled(gboolean value)
190 void *agent = _bt_hal_get_adapter_agent();
194 return _gap_agent_set_canceled(agent, value);
197 void _bt_hal_initialize_adapter_agent(void)
200 ERR("Adapter agent already exist!");
204 adapter_agent = _bt_hal_create_agent(BT_HAL_ADAPTER_AGENT_PATH, TRUE);
205 if (!adapter_agent) {
206 ERR("Fail to register agent");
211 void _bt_hal_destroy_adapter_agent(void)
214 _bt_hal_destroy_agent(adapter_agent);
215 adapter_agent = NULL;
218 void* _bt_hal_get_adapter_agent(void)
220 return adapter_agent;
223 void _bt_hal_enable_gap_auth_notifications(unsigned int type, gboolean enable)
225 INFO("type: %d, enable: %d", type, enable);
228 case BT_PASSKEY_CONFIRMATION:
229 /* Note: Currently not used for notification sending, should be used when required */
230 passkey_confirm_notification = enable;
232 case BT_PASSKEY_DISPLAY:
233 passkey_display_notification = enable;
235 case BT_PASSKEY_ENTRY:
236 /* Note: Currently not used for notification sending, should be used when required */
237 passkey_notification = enable;
239 case BT_PINCODE_ENTRY:
240 pincode_notification = enable;
243 ERR("Unknown type: %d", type);
247 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid)
249 struct hal_ev_authorize_request ev;
250 memset(&ev, 0, sizeof(ev));
252 DBG("Remote Device address [%s]", address);
254 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
256 /* UUID received in authorization request (In case of HFP unit, UUID received from Bluez
257 would be of that of Audio Gateway UUID (0x111f) */
258 ev.service_id = _bt_convert_uuid_string_to_service_id(uuid);
260 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
262 event_cb(HAL_EV_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
267 static void __bt_hal_send_rfcomm_authorize_request_event(const gchar *address, const char *uuid, const char *name, char *path, int fd)
269 struct hal_ev_sock_conn_auth ev;
271 DBG("Remote Device address [%s], uuid: %s", address, uuid);
273 memset(&ev, 0, sizeof(ev));
274 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
275 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid);
278 g_strlcpy((char *)ev.name, name, BT_HAL_DEVICE_NAME_LENGTH_MAX);
281 g_strlcpy((char *)ev.path, path, BT_HAL_PATH_NAME_LENGTH_MAX);
285 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
287 event_cb(HAL_EV_SOCK_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
293 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
296 struct hal_ev_pin_request ev;
297 memset(&ev, 0, sizeof(ev));
299 DBG("Remote Device address [%s]", address);
300 DBG("Remote Device Name [%s]", name);
301 DBG("Remote Device COD [%u]", cod);
303 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
305 memcpy(ev.name, name, strlen(name)+1);
306 ev.class_of_dev = cod;
308 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
310 DBG("Sending PIN REQUEST");
311 event_cb(HAL_EV_PIN_REQUEST, (void*)&ev, sizeof(ev));
318 void __bt_hal_get_auth_info(GVariant *reply, char *auth_info)
322 char *manufacturer_data = NULL;
323 int manufacturer_data_len;
324 gboolean is_alias_set;
325 GVariantIter *value_iter;
329 tmp_value = g_variant_lookup_value(reply, "IsAliasSet",
330 G_VARIANT_TYPE_BOOLEAN);
332 is_alias_set = g_variant_get_boolean(tmp_value);
333 g_variant_unref(tmp_value);
335 is_alias_set = FALSE;
337 if (is_alias_set == FALSE) {
338 tmp_value = g_variant_lookup_value(reply, "LagacyManufacturerDataLen",
339 G_VARIANT_TYPE_UINT16);
341 manufacturer_data_len = g_variant_get_uint16(tmp_value);
342 if (manufacturer_data_len >
343 MAX_MANUFACTURE_LEN) {
344 ERR("manufacturer_data_len is too long");
345 manufacturer_data_len = MAX_MANUFACTURE_LEN;
347 g_variant_unref(tmp_value);
349 manufacturer_data_len = 0;
351 tmp_value = g_variant_lookup_value(reply, "LagacyManufacturerData",
352 G_VARIANT_TYPE_ARRAY);
354 if ((manufacturer_data_len == 0) ||
355 manufacturer_data_len != g_variant_get_size(tmp_value)) {
356 ERR("manufacturer data length doesn't match");
357 manufacturer_data_len = 0;
358 manufacturer_data = NULL;
360 manufacturer_data = g_malloc0(manufacturer_data_len);
361 g_variant_get(tmp_value, "ay", &value_iter);
362 while (g_variant_iter_loop(value_iter, "y", &m_value))
363 manufacturer_data[i++] = m_value;
365 g_variant_iter_free(value_iter);
367 g_variant_unref(tmp_value);
369 INFO("manufacture data is not a G_VARIANT_TYPE_ARRAY ");
370 manufacturer_data_len = 0;
371 manufacturer_data = NULL;
373 /*minimum Size of the samsung specific manufacturer data is greater than 30 */
374 if (manufacturer_data_len < 30) {
375 g_free(manufacturer_data);
378 if (manufacturer_data[0] != 0x00 || manufacturer_data[1] != 0x75) {
379 DBG("This is not a samsung specific manufaturer data");
380 g_free(manufacturer_data);
384 /* 2 samsung (0x00 0x75) + 1 (control and version) + 1 (service ID) +
385 1 (discovery version) + 1 (associated service ID)
386 2 (Proxamity and locality) + 2 (Device type and icon) */
390 memcpy(auth_info, &(manufacturer_data[cursor]), 5);
392 g_free(manufacturer_data);
395 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
397 uint32_t device_class;
398 const gchar *address;
399 unsigned char auth_info[5] = {0, };
401 GVariant *reply = NULL;
402 GVariant *reply_temp = NULL;
406 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
408 if (reply_temp == NULL) {
409 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
414 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
416 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
417 g_variant_get(tmp_value, "u", &device_class);
418 G_VARIANT_UNREF(tmp_value);
420 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
421 g_variant_get(tmp_value, "s", &address);
422 G_VARIANT_UNREF(tmp_value);
424 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
425 g_variant_get(tmp_value, "s", &name);
426 G_VARIANT_UNREF(tmp_value);
431 if (headed_plugin_info->plugin_headed_enabled) {
432 __bt_hal_get_auth_info(reply, (char *)auth_info);
433 if (__bt_hal_device_is_hid_keyboard(device_class)) {
434 char str_passkey[BT_HAL_PASSKEY_MAX_LENGTH + 1] = { 0 };
436 DBG("Device is HID Keyboard");
437 if (__bt_hal_device_generate_passkey(str_passkey,
438 BT_HAL_PASSKEY_MAX_LENGTH) != 0) {
439 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
444 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
447 DBG("Launch BT Syspopup");
448 headed_plugin_info->headed_plugin->bt_launch_system_popup(
449 BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
450 name, auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
451 } else if (__bt_hal_device_is_auto_response(device_class, address, name)) {
452 DBG("Device is of Type Auto response, send event to HAL");
453 __bt_hal_send_pin_request_event(address, name, device_class);
454 } else if (pincode_notification) {
455 DBG("pincode_notification is enabled, send event to HAL");
456 __bt_hal_send_pin_request_event(address, name, device_class);
458 DBG("Device is not of Auto response class, Show PIN Entry");
459 headed_plugin_info->headed_plugin->bt_launch_system_popup(
460 BT_HAL_AGENT_EVENT_PIN_REQUEST, name, auth_info,
461 NULL, NULL, _gap_agent_get_path(agent));
464 INFO("Plugin Headed not Enabled");
465 __bt_hal_send_pin_request_event(address, name, device_class);
469 g_variant_unref(reply);
470 g_variant_unref(reply_temp);
471 __bt_hal_agent_release_memory();
478 /* BT_SSP_VARIANT_PASSKEY_CONFIRMATION */
479 /* BT_SSP_VARIANT_PASSKEY_NOTIFICATION */
480 /* BT_SSP_VARIANT_PASSKEY_ENTRY */
481 /* BT_SSP_VARIANT_CONSENT */
483 static void __bt_hal_send_ssp_request_events(const gchar *address,
487 unsigned char variant)
489 struct hal_ev_ssp_request ev;
490 memset(&ev, 0, sizeof(ev));
491 DBG("sizeof ev [%zu]", sizeof(ev));
493 DBG("Remote Device address [%s]", address);
494 DBG("Remote Device Name [%s]", name);
495 DBG("Remote Device passkey [%d]", passkey);
496 DBG("Remote Device pairing variant [0x%x]", variant);
497 DBG("Remote Device cod [%d]", cod);
499 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
501 memcpy(ev.name, name, strlen(name)+1);
502 ev.class_of_dev = cod;
503 ev.pairing_variant = variant;
504 ev.passkey = passkey;
506 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
508 DBG("Sending SSP type [%d]", variant);
509 event_cb(HAL_EV_SSP_REQUEST, (void*)&ev, sizeof(ev));
516 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
519 const gchar *address;
521 unsigned char auth_info[5] = {0, };
523 uint32_t device_class;
524 GVariant *reply = NULL;
525 GVariant *reply_temp = NULL;
526 GVariant *tmp_value = NULL;
529 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
530 if (reply_temp == NULL) {
531 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
536 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
538 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
539 g_variant_get(tmp_value, "s", &address);
540 G_VARIANT_UNREF(tmp_value);
542 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
546 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
547 g_variant_get(tmp_value, "s", &name);
548 G_VARIANT_UNREF(tmp_value);
550 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
551 g_variant_get(tmp_value, "u", &device_class);
552 G_VARIANT_UNREF(tmp_value);
557 str_passkey = g_strdup_printf("%d", passkey);
559 __bt_hal_get_auth_info(reply, (char *)auth_info);
561 DBG("KEYBOARD_PASSKEY_REQUEST");
563 if (passkey_display_notification) {
564 DBG("passkey_display_notification is enabled, send event to HAL");
565 __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
566 BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
567 } else if (headed_plugin_info->plugin_headed_enabled) {
568 INFO("Plugin Headed Enabled");
569 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
570 auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
572 INFO("Plugin Headed not Enabled");
573 __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
574 BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
579 g_variant_unref(reply);
580 g_variant_unref(reply_temp);
581 __bt_hal_agent_release_memory();
588 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
590 const gchar *address;
592 unsigned char auth_info[5] = {0, };
593 uint32_t device_class;
594 GVariant *reply = NULL;
595 GVariant *reply_temp = NULL;
599 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
601 if (reply_temp == NULL) {
602 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
607 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
609 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
610 g_variant_get(tmp_value, "s", &address);
611 G_VARIANT_UNREF(tmp_value);
613 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
617 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
618 g_variant_get(tmp_value, "s", &name);
619 G_VARIANT_UNREF(tmp_value);
621 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
622 g_variant_get(tmp_value, "u", &device_class);
623 G_VARIANT_UNREF(tmp_value);
628 DBG("PASSKEY_REQUEST");
630 __bt_hal_get_auth_info(reply, (char *)auth_info);
632 if (headed_plugin_info->plugin_headed_enabled) {
633 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_REQUEST, name, auth_info,
634 NULL, NULL, _gap_agent_get_path(agent));
636 __bt_hal_send_ssp_request_events(address, name, 0, device_class,
637 BT_SSP_VARIANT_PASSKEY_ENTRY);
641 g_variant_unref(reply);
642 g_variant_unref(reply_temp);
643 __bt_hal_agent_release_memory();
650 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
653 const gchar *address;
656 uint32_t device_class;
657 GVariant *reply_temp = NULL;
658 GVariant *reply = NULL;
660 DBG("+ passkey[%.6d]", passkey);
661 DBG("Agent Path [%s]", agent->path);
663 snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
665 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
667 if (reply_temp == NULL) {
668 ERR("####Device doesn't exist####");
669 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
673 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
675 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
676 g_variant_get(tmp_value, "s", &address);
677 G_VARIANT_UNREF(tmp_value);
679 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
680 g_variant_get(tmp_value, "s", &name);
681 G_VARIANT_UNREF(tmp_value);
683 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
684 g_variant_get(tmp_value, "u", &device_class);
685 G_VARIANT_UNREF(tmp_value);
690 if (headed_plugin_info->plugin_headed_enabled) {
691 unsigned char auth_info[5] = {0, };
693 DBG("LAUNCH SYSPOPUP");
694 DBG("Name [%s]", name);
695 DBG("Passkey [%s]", str_passkey);
697 __bt_hal_get_auth_info(reply, (char *)auth_info);
698 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
699 auth_info, str_passkey, NULL,
700 _gap_agent_get_path(agent));
702 DBG("Headless Confirmation");
704 if (TIZEN_FEATURE_BLUEZ_SPEAKER_REFERENCE) {
705 /* Reply the ssp confirmation automaticaly */
706 gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
709 __bt_hal_send_ssp_request_events(address, name, passkey,
710 device_class, BT_SSP_VARIANT_PASSKEY_CONFIRMATION);
714 g_variant_unref(reply);
715 g_variant_unref(reply_temp);
716 __bt_hal_agent_release_memory();
721 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
724 const gchar *address;
728 GVariant *reply = NULL;
729 GVariant *reply_temp = NULL;
731 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
732 bt_hal_agent_osp_server_t *osp_server;
735 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
736 if (reply_temp == NULL) {
737 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
741 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
743 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
744 g_variant_get(tmp_value, "s", &address);
745 G_VARIANT_UNREF(tmp_value);
747 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
751 tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
752 g_variant_get(tmp_value, "s", &name);
753 G_VARIANT_UNREF(tmp_value);
757 tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
758 g_variant_get(tmp_value, "b", &trust);
759 G_VARIANT_UNREF(tmp_value);
761 tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
762 g_variant_get(tmp_value, "b", &paired);
763 G_VARIANT_UNREF(tmp_value);
764 if ((paired == FALSE) && (trust == FALSE)) {
765 ERR("No paired & No trusted device");
766 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
770 INFO("Authorization request for device [%s] Service:[%s]\n", address + 12, uuid);
773 DBG("Trusted device, so authorize\n");
774 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
778 if (!strcasecmp(uuid, BT_HAL_HID_UUID)) {
779 gboolean is_connectable = __bt_hal_is_hid_device_connectable();
780 DBG("Automatically %s authorization for HID",
781 is_connectable ? "accept" : "reject");
782 if (is_connectable == TRUE)
783 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
785 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
789 if (!strcasecmp(uuid, BT_HAL_HFP_AUDIO_GATEWAY_UUID) ||
790 !strcasecmp(uuid, BT_HAL_HSP_AUDIO_GATEWAY_UUID) ||
791 !strcasecmp(uuid, BT_HAL_HFP_HF_UUID) ||
792 !strcasecmp(uuid, BT_HAL_HSP_HS_UUID) ||
793 !strcasecmp(uuid, BT_HAL_A2DP_PROFILE_UUID) ||
794 !strcasecmp(uuid, BT_HAL_HID_DEVICE_UUID) ||
795 !strcasecmp(uuid, BT_HAL_SAP_UUID_OLD) ||
796 !strcasecmp(uuid, BT_HAL_SAP_UUID_NEW) ||
798 !strcasecmp(uuid, BT_HAL_IOTIVITY_UUID) ||
800 !strcasecmp(uuid, BT_HAL_AVRCP_TARGET_UUID)) {
801 __bt_hal_send_authorize_request_event(address, uuid);
806 if (!strcasecmp(uuid, BT_HAL_OPP_UUID)) {
807 if (NULL != _bt_hal_gap_agent_find_osp_server_by_type(
808 agent->osp_servers, BT_OSP_SERVER_OBEX, NULL)) {
809 INFO("OSP server for OPP found, send event");
810 __bt_hal_send_authorize_request_event(address, uuid);
813 INFO("Native OPP server, auto accept");
814 gap_agent_reply_authorize(agent,
815 GAP_AGENT_ACCEPT, NULL);
820 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
821 /* If user only listens(without accepts) to rfcomm server, occurs connection requested cb not popup */
822 osp_server = _bt_hal_gap_agent_find_osp_server_by_type(agent->osp_servers, BT_OSP_SERVER_RFCOMM, uuid);
824 INFO("Found rfcomm osp server. path: %s, fd: %d", osp_server->path, osp_server->fd);
825 __bt_hal_send_rfcomm_authorize_request_event(address, uuid, name, osp_server->path, osp_server->fd);
829 if (_is_rfcomm_server_uuid(uuid)) {
830 __bt_hal_send_rfcomm_authorize_request_event(address, uuid, NULL, NULL, -1);
836 if (trust || !headed_plugin_info->plugin_headed_enabled) {
837 INFO("Trusted or Headless device, so authorize\n");
838 gap_agent_reply_authorize(agent,
839 GAP_AGENT_ACCEPT, NULL);
844 if (headed_plugin_info->plugin_headed_enabled) {
845 unsigned char auth_info[5] = {0, };
846 int request_type = BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST;
848 __bt_hal_get_auth_info(reply, (char *)auth_info);
850 if (!strcasecmp(uuid, BT_HAL_OPP_UUID))
851 request_type = BT_HAL_AGENT_EVENT_EXCHANGE_REQUEST;
852 else if (!strcasecmp(uuid, BT_HAL_PBAP_UUID))
853 request_type = BT_HAL_AGENT_EVENT_PBAP_REQUEST;
854 else if (!strcasecmp(uuid, BT_HAL_MAP_UUID))
855 request_type = BT_HAL_AGENT_EVENT_MAP_REQUEST;
857 headed_plugin_info->headed_plugin->bt_launch_system_popup(request_type, name, auth_info, NULL, NULL,
858 _gap_agent_get_path(agent));
862 g_variant_unref(reply);
863 g_variant_unref(reply_temp);
864 __bt_hal_agent_release_memory();
869 static gboolean __bt_hal_authorize_cancel_request(GapAgentPrivate *agent,
872 DBG("On Going Authorization is cancelled by remote [%s]", address);
873 gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
875 if (headed_plugin_info->plugin_headed_enabled)
876 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
878 __bt_hal_agent_release_memory();
882 static gboolean __bt_hal_pairing_cancel_request(GapAgentPrivate *agent, const char *address)
884 DBG("On Going Pairing is cancelled by remote [%s]", address);
886 if (headed_plugin_info->plugin_headed_enabled)
887 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
889 __bt_hal_agent_release_memory();
893 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class)
895 switch ((dev_class & 0x1f00) >> 8) {
897 switch ((dev_class & 0xc0) >> 6) {
899 /* input-keyboard" */
908 static gboolean __bt_hal_is_hid_device_connectable(void)
910 GDBusProxy *proxy = NULL;
911 GVariant *reply = NULL;
913 gboolean connectable = FALSE;
915 proxy = _bt_hal_get_hid_agent_proxy();
919 reply = g_dbus_proxy_call_sync(proxy, "IsHidConnectable", NULL,
920 G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &err);
922 ERR("Error returned in method call");
924 ERR("Error message = %s", err->message);
929 g_variant_get(reply, "(b)", &connectable);
930 g_variant_unref(reply);
932 g_object_unref(proxy);
934 INFO("HID Device is %s",
935 connectable ? "Connectable" : "Non-connectable");
940 static int __bt_hal_device_generate_passkey(char *passkey, int size)
945 unsigned int value = 0;
953 random_fd = open("/dev/urandom", O_RDONLY);
958 for (i = 0; i < size; i++) {
959 len = read(random_fd, &value, sizeof(value));
961 passkey[i] = '0' + (value % 10);
966 DBG("passkey: %s", passkey);
971 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
977 pch = strtok_r(buffer, "= ,", &last);
982 while ((pch = strtok_r(NULL, ",", &last))) {
983 if (0 == g_strcmp0(pch, address)) {
984 DBG("Match found\n");
991 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
992 const char *partial_name)
997 pch = strtok_r(buffer, "= ,", &last);
1002 while ((pch = strtok_r(NULL, ",", &last))) {
1003 if (g_str_has_prefix(partial_name, pch)) {
1004 DBG("Match found\n");
1011 static gboolean __bt_hal_device_is_device_blacklisted(const char *address,
1023 fp = fopen(BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
1026 ERR("Unable to open blacklist file");
1030 fseek(fp, 0, SEEK_END);
1033 DBG("size is not a positive number");
1040 buffer = g_malloc0(sizeof(char) * size);
1041 /* Fix : NULL_RETURNS */
1042 if (buffer == NULL) {
1043 ERR("Fail to allocate memory");
1047 result = fread((char *)buffer, 1, size, fp);
1049 if (result != size) {
1055 lines = g_strsplit_set(buffer, BT_HAL_AGENT_NEW_LINE, 0);
1058 if (lines == NULL) {
1059 ERR("No lines in the file");
1063 for (i = 0; lines[i] != NULL; i++) {
1064 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
1065 if (__bt_hal_find_device_by_address_exactname(
1068 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
1069 if (__bt_hal_find_device_by_address_exactname(
1072 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
1073 if (__bt_hal_find_device_by_partial_name(lines[i],
1076 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
1077 if (__bt_hal_find_device_by_address_exactname(
1085 DBG("Found the device");
1090 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
1091 const gchar *address, const gchar *name)
1093 gboolean is_headset = FALSE;
1094 gboolean is_mouse = FALSE;
1095 unsigned int adapter_class = 0;
1096 char lap_address[BT_HAL_LOWER_ADDRESS_LENGTH];
1098 DBG("bt_agent_is_headset_class, %d +", dev_class);
1100 if (address == NULL)
1103 _bt_hal_dbus_get_adapter_class(&adapter_class);
1105 if (((adapter_class & 0x1f00) >> 8) == 0x05)
1107 DBG("Adapter is Peripheral, do not response automatically");
1111 switch ((dev_class & 0x1f00) >> 8) {
1113 switch ((dev_class & 0xfc) >> 2) {
1123 case 0x0b: /* VCR */
1124 case 0x0c: /* Video Camera */
1125 case 0x0d: /* Camcorder */
1128 /* Other audio device */
1134 switch (dev_class & 0xff) {
1135 case 0x80: /* 0x80: Pointing device(Mouse) */
1139 case 0x40: /* 0x40: input device (BT keyboard) */
1141 /* Get the LAP(Lower Address part) */
1142 g_strlcpy(lap_address, address, sizeof(lap_address));
1144 /* Need to Auto pair the blacklisted Keyboard */
1145 if (__bt_hal_device_is_device_blacklisted(lap_address, name) != TRUE) {
1146 DBG("Device is not black listed\n");
1149 ERR("Device is black listed\n");
1155 if ((!is_headset) && (!is_mouse))
1158 /* Get the LAP(Lower Address part) */
1159 g_strlcpy(lap_address, address, sizeof(lap_address));
1161 DBG("Device address = %s\n", address);
1162 DBG("Address 3 byte = %s\n", lap_address);
1164 if (__bt_hal_device_is_device_blacklisted(lap_address, name)) {
1165 ERR("Device is black listed\n");
1172 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface)
1174 GError *error = NULL;
1177 reply = g_dbus_proxy_call_sync(device,
1178 "GetAll", g_variant_new("(s)", interface),
1179 G_DBUS_CALL_FLAGS_NONE, -1,
1181 if (reply == NULL) {
1182 ERR("GetAll dBUS-RPC failed");
1184 ERR("D-Bus API failure: errCode[%x], message[%s]",
1185 error->code, error->message);
1186 g_clear_error(&error);
1194 static void __bt_hal_agent_release_memory(void)
1196 /* Release Malloc Memory*/
1199 /* Release Stack Memory*/
1203 static inline void stack_trim(void)
1209 unsigned int stacktop;
1212 asm volatile ("mov %0,sp " : "=r"(sp));
1214 sprintf(buf, "/proc/%d/maps", getpid());
1215 file = fopen(buf, "r");
1216 while (fgets(buf, BUF_SIZE, file) != NULL) {
1217 if (strstr(buf, "[stack]")) {
1225 sscanf(buf, "%x-", &stacktop);
1226 if (madvise((void *)PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop,
1228 perror("stack madvise fail");