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-l2cap-le-dbus-handler.h"
54 #include "bt-hal-device-dbus-handler.h"
55 #include "bt-hal-event-receiver.h"
57 #include <bt-hal-agent.h>
58 #include <bt-hal-gap-agent.h>
59 #include <bt-hal-dbus-common-utils.h>
61 /* TODO_40 : 4.0 merge */
62 #include "bt-internal-types.h"
64 #define BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE (APP_SYSCONFDIR"/auto-pair-blacklist")
65 #define BT_HAL_AGENT_NEW_LINE "\r\n"
67 #define PAGE_SIZE (1 << 12)
68 #define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1)))
69 #define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
70 #define PAGE_ALIGN(addr) _ALIGN_DOWN(addr, PAGE_SIZE)
71 #define BT_HAL_PIN_MAX_LENGTH 16
72 #define BT_HAL_PASSKEY_MAX_LENGTH 4
73 #define BT_HAL_LOWER_ADDRESS_LENGTH 9
74 #define BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
75 #define BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT 3
77 #define G_VARIANT_UNREF(variant) \
78 g_variant_unref(variant); \
80 #define BT_HAL_MAX_EVENT_STR_LENGTH 50
82 static void *adapter_agent = NULL;
83 static gboolean passkey_display_notification = FALSE;
84 static gboolean passkey_confirm_notification = FALSE;
85 static gboolean passkey_notification = FALSE;
86 static gboolean pincode_notification = FALSE;
88 /* Forward delcaration */
89 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
91 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device);
92 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
94 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device);
95 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
97 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
99 static gboolean __bt_hal_authorize_cancel_request(GapAgentPrivate *agent, const char *address);
100 static gboolean __bt_hal_pairing_cancel_request(GapAgentPrivate *agent, const char *address);
101 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface);
102 static void __bt_hal_agent_release_memory(void);
103 static inline void stack_trim(void);
105 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class);
106 static gboolean __bt_hal_is_hid_device_connectable(void);
107 static int __bt_hal_device_generate_passkey(char *passkey, int size);
108 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
109 const gchar *address, const gchar *name);
110 static gboolean __bt_hal_device_is_device_blacklisted(const char *address, const char *name);
111 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
112 const char *address);
113 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
114 const char *partial_name);
115 static void __bt_hal_send_ssp_request_events(const gchar *address, const gchar *name,
116 guint passkey, uint32_t cod, unsigned char variant);
117 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid);
119 void* _bt_hal_create_agent(const char *path, gboolean adapter)
121 GAP_AGENT_FUNC_CB func_cb;
122 GDBusProxy *adapter_proxy;
123 GapAgentPrivate *agent;
126 adapter_proxy = _bt_hal_get_adapter_proxy();
130 func_cb.pincode_func = __bt_hal_pincode_request;
131 func_cb.display_func = __bt_hal_display_request;
132 func_cb.passkey_func = __bt_hal_passkey_request;
133 func_cb.confirm_func = __bt_hal_confirm_request;
134 func_cb.authorize_func = __bt_hal_authorize_request;
135 func_cb.pairing_cancel_func = __bt_hal_pairing_cancel_request;
136 func_cb.authorization_cancel_func = __bt_hal_authorize_cancel_request;
139 agent = g_new0(GapAgentPrivate, 1);
141 _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
144 if (!_gap_agent_register(agent)) {
145 ERR("gap agent registration failed!");
146 _bt_hal_destroy_agent(agent);
154 void _bt_hal_destroy_agent(void *agent)
160 _gap_agent_reset_dbus((GapAgentPrivate *)agent);
166 gboolean _bt_hal_agent_is_canceled(void)
168 void *agent = _bt_hal_get_adapter_agent();
172 return _gap_agent_is_canceled(agent);
175 int _bt_hal_agent_reply_cancellation(void)
177 void *agent = _bt_hal_get_adapter_agent();
179 return BT_STATUS_FAIL;
181 if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
182 ERR("Fail to reply agent");
183 return BT_STATUS_FAIL;
185 DBG("gap agent cancellation done successfully!");
186 return BT_STATUS_SUCCESS;
190 void _bt_hal_agent_set_canceled(gboolean value)
192 void *agent = _bt_hal_get_adapter_agent();
196 return _gap_agent_set_canceled(agent, value);
199 void _bt_hal_initialize_adapter_agent(void)
202 ERR("Adapter agent already exist!");
206 adapter_agent = _bt_hal_create_agent(BT_HAL_ADAPTER_AGENT_PATH, TRUE);
207 if (!adapter_agent) {
208 ERR("Fail to register agent");
213 void _bt_hal_destroy_adapter_agent(void)
216 _bt_hal_destroy_agent(adapter_agent);
217 adapter_agent = NULL;
220 void* _bt_hal_get_adapter_agent(void)
222 return adapter_agent;
225 void _bt_hal_enable_gap_auth_notifications(unsigned int type, gboolean enable)
227 INFO("type: %d, enable: %d", type, enable);
230 case BT_PASSKEY_CONFIRMATION:
231 /* Note: Currently not used for notification sending, should be used when required */
232 passkey_confirm_notification = enable;
234 case BT_PASSKEY_DISPLAY:
235 passkey_display_notification = enable;
237 case BT_PASSKEY_ENTRY:
238 /* Note: Currently not used for notification sending, should be used when required */
239 passkey_notification = enable;
241 case BT_PINCODE_ENTRY:
242 pincode_notification = enable;
245 ERR("Unknown type: %d", type);
249 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid)
251 struct hal_ev_authorize_request ev;
252 memset(&ev, 0, sizeof(ev));
254 DBG("Remote Device address [%s]", address);
256 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
258 /* UUID received in authorization request (In case of HFP unit, UUID received from Bluez
259 would be of that of Audio Gateway UUID (0x111f) */
260 ev.service_id = _bt_convert_uuid_string_to_service_id(uuid);
262 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
264 event_cb(HAL_EV_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
269 static void __bt_hal_send_rfcomm_authorize_request_event(const gchar *address, const char *uuid, const char *name, char *path, int fd)
271 struct hal_ev_sock_conn_auth ev;
273 DBG("Remote Device address [%s], uuid: %s", address, uuid);
275 memset(&ev, 0, sizeof(ev));
276 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
277 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid);
280 g_strlcpy((char *)ev.name, name, BT_HAL_DEVICE_NAME_LENGTH_MAX);
283 g_strlcpy((char *)ev.path, path, BT_HAL_PATH_NAME_LENGTH_MAX);
287 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
289 event_cb(HAL_EV_SOCK_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
295 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
298 struct hal_ev_pin_request ev;
299 memset(&ev, 0, sizeof(ev));
301 DBG("Remote Device address [%s]", address);
302 DBG("Remote Device Name [%s]", name);
303 DBG("Remote Device COD [%u]", cod);
305 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
307 memcpy(ev.name, name, strlen(name)+1);
308 ev.class_of_dev = cod;
310 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
312 DBG("Sending PIN REQUEST");
313 event_cb(HAL_EV_PIN_REQUEST, (void*)&ev, sizeof(ev));
320 void __bt_hal_get_auth_info(GVariant *reply, char *auth_info)
324 char *manufacturer_data = NULL;
325 int manufacturer_data_len;
326 gboolean is_alias_set;
327 GVariantIter *value_iter;
331 tmp_value = g_variant_lookup_value(reply, "IsAliasSet",
332 G_VARIANT_TYPE_BOOLEAN);
334 is_alias_set = g_variant_get_boolean(tmp_value);
335 g_variant_unref(tmp_value);
337 is_alias_set = FALSE;
339 if (is_alias_set == FALSE) {
340 tmp_value = g_variant_lookup_value(reply, "LagacyManufacturerDataLen",
341 G_VARIANT_TYPE_UINT16);
343 manufacturer_data_len = g_variant_get_uint16(tmp_value);
344 if (manufacturer_data_len >
345 MAX_MANUFACTURE_LEN) {
346 ERR("manufacturer_data_len is too long");
347 manufacturer_data_len = MAX_MANUFACTURE_LEN;
349 g_variant_unref(tmp_value);
351 manufacturer_data_len = 0;
353 tmp_value = g_variant_lookup_value(reply, "LagacyManufacturerData",
354 G_VARIANT_TYPE_ARRAY);
356 if ((manufacturer_data_len == 0) ||
357 manufacturer_data_len != g_variant_get_size(tmp_value)) {
358 ERR("manufacturer data length doesn't match");
359 manufacturer_data_len = 0;
360 manufacturer_data = NULL;
362 manufacturer_data = g_malloc0(manufacturer_data_len);
363 g_variant_get(tmp_value, "ay", &value_iter);
364 while (g_variant_iter_loop(value_iter, "y", &m_value))
365 manufacturer_data[i++] = m_value;
367 g_variant_iter_free(value_iter);
369 g_variant_unref(tmp_value);
371 INFO("manufacture data is not a G_VARIANT_TYPE_ARRAY ");
372 manufacturer_data_len = 0;
373 manufacturer_data = NULL;
375 /*minimum Size of the samsung specific manufacturer data is greater than 30 */
376 if (manufacturer_data_len < 30) {
377 g_free(manufacturer_data);
380 if (manufacturer_data[0] != 0x00 || manufacturer_data[1] != 0x75) {
381 DBG("This is not a samsung specific manufaturer data");
382 g_free(manufacturer_data);
386 /* 2 samsung (0x00 0x75) + 1 (control and version) + 1 (service ID) +
387 1 (discovery version) + 1 (associated service ID)
388 2 (Proxamity and locality) + 2 (Device type and icon) */
392 memcpy(auth_info, &(manufacturer_data[cursor]), 5);
394 g_free(manufacturer_data);
397 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
399 uint32_t device_class;
400 gchar *address = NULL;
401 unsigned char auth_info[5] = {0, };
403 GVariant *reply = NULL;
404 GVariant *reply_temp = NULL;
405 GVariant *tmp_value = NULL;
408 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
410 if (reply_temp == NULL) {
411 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
416 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
418 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
419 g_variant_get(tmp_value, "u", &device_class);
420 G_VARIANT_UNREF(tmp_value);
422 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
423 g_variant_get(tmp_value, "s", &address);
424 G_VARIANT_UNREF(tmp_value);
426 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
427 g_variant_get(tmp_value, "s", &name);
428 G_VARIANT_UNREF(tmp_value);
431 name = g_strdup(address);
433 if (headed_plugin_info->plugin_headed_enabled) {
434 __bt_hal_get_auth_info(reply, (char *)auth_info);
435 if (__bt_hal_device_is_hid_keyboard(device_class)) {
436 char str_passkey[BT_HAL_PASSKEY_MAX_LENGTH + 1] = { 0 };
438 DBG("Device is HID Keyboard");
439 if (__bt_hal_device_generate_passkey(str_passkey,
440 BT_HAL_PASSKEY_MAX_LENGTH) != 0) {
441 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
446 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
449 DBG("Launch BT Syspopup");
450 headed_plugin_info->headed_plugin->bt_launch_system_popup(
451 BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
452 address, auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
453 } else if (__bt_hal_device_is_auto_response(device_class, address, name)) {
454 DBG("Device is of Type Auto response, send event to HAL");
455 __bt_hal_send_pin_request_event(address, name, device_class);
456 } else if (pincode_notification) {
457 DBG("pincode_notification is enabled, send event to HAL");
458 __bt_hal_send_pin_request_event(address, name, device_class);
460 DBG("Device is not of Auto response class, Show PIN Entry");
461 headed_plugin_info->headed_plugin->bt_launch_system_popup(
462 BT_HAL_AGENT_EVENT_PIN_REQUEST, name, address,
463 auth_info, NULL, NULL, _gap_agent_get_path(agent));
466 INFO("Plugin Headed not Enabled");
467 __bt_hal_send_pin_request_event(address, name, device_class);
473 g_variant_unref(reply);
474 g_variant_unref(reply_temp);
475 __bt_hal_agent_release_memory();
482 /* BT_SSP_VARIANT_PASSKEY_CONFIRMATION */
483 /* BT_SSP_VARIANT_PASSKEY_NOTIFICATION */
484 /* BT_SSP_VARIANT_PASSKEY_ENTRY */
485 /* BT_SSP_VARIANT_CONSENT */
487 static void __bt_hal_send_ssp_request_events(const gchar *address,
491 unsigned char variant)
493 struct hal_ev_ssp_request ev;
494 memset(&ev, 0, sizeof(ev));
495 DBG("sizeof ev [%zu]", sizeof(ev));
497 DBG("Remote Device address [%s]", address);
498 DBG("Remote Device Name [%s]", name);
499 DBG("Remote Device passkey [%d]", passkey);
500 DBG("Remote Device pairing variant [0x%x]", variant);
501 DBG("Remote Device cod [%d]", cod);
503 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
505 memcpy(ev.name, name, strlen(name)+1);
506 ev.class_of_dev = cod;
507 ev.pairing_variant = variant;
508 ev.passkey = passkey;
510 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
512 DBG("Sending SSP type [%d]", variant);
513 event_cb(HAL_EV_SSP_REQUEST, (void*)&ev, sizeof(ev));
520 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
523 gchar *address = NULL;
525 unsigned char auth_info[5] = {0, };
526 char *str_passkey = NULL;
527 uint32_t device_class;
528 GVariant *reply = NULL;
529 GVariant *reply_temp = NULL;
530 GVariant *tmp_value = NULL;
533 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
534 if (reply_temp == NULL) {
535 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
540 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
542 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
543 g_variant_get(tmp_value, "s", &address);
544 G_VARIANT_UNREF(tmp_value);
546 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
550 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
551 g_variant_get(tmp_value, "s", &name);
552 G_VARIANT_UNREF(tmp_value);
554 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
555 g_variant_get(tmp_value, "u", &device_class);
556 G_VARIANT_UNREF(tmp_value);
559 name = g_strdup(address);
561 str_passkey = g_strdup_printf("%d", passkey);
563 __bt_hal_get_auth_info(reply, (char *)auth_info);
565 DBG("KEYBOARD_PASSKEY_REQUEST");
567 if (passkey_display_notification) {
568 DBG("passkey_display_notification is enabled, send event to HAL");
569 __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
570 BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
571 } else if (headed_plugin_info->plugin_headed_enabled) {
572 INFO("Plugin Headed Enabled");
573 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
574 name, address, auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
576 INFO("Plugin Headed not Enabled");
577 __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
578 BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
585 g_variant_unref(reply);
586 g_variant_unref(reply_temp);
587 __bt_hal_agent_release_memory();
594 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
596 gchar *address = NULL;
598 unsigned char auth_info[5] = {0, };
599 uint32_t device_class;
600 GVariant *reply = NULL;
601 GVariant *reply_temp = NULL;
602 GVariant *tmp_value = NULL;
605 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
607 if (reply_temp == NULL) {
608 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
613 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
615 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
616 g_variant_get(tmp_value, "s", &address);
617 G_VARIANT_UNREF(tmp_value);
619 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
623 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
624 g_variant_get(tmp_value, "s", &name);
625 G_VARIANT_UNREF(tmp_value);
627 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
628 g_variant_get(tmp_value, "u", &device_class);
629 G_VARIANT_UNREF(tmp_value);
632 name = g_strdup(address);
634 DBG("PASSKEY_REQUEST");
636 __bt_hal_get_auth_info(reply, (char *)auth_info);
638 if (headed_plugin_info->plugin_headed_enabled) {
639 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_REQUEST,
640 name, address, auth_info, NULL, NULL, _gap_agent_get_path(agent));
642 __bt_hal_send_ssp_request_events(address, name, 0, device_class,
643 BT_SSP_VARIANT_PASSKEY_ENTRY);
649 g_variant_unref(reply);
650 g_variant_unref(reply_temp);
651 __bt_hal_agent_release_memory();
658 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
661 gchar *address = NULL;
664 uint32_t device_class;
665 GVariant *reply_temp = NULL;
666 GVariant *reply = NULL;
667 GVariant *tmp_value = NULL;
668 DBG("+ passkey[%.6d]", passkey);
669 DBG("Agent Path [%s]", agent->path);
671 snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
673 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
675 if (reply_temp == NULL) {
676 ERR("####Device doesn't exist####");
677 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
681 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
683 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
684 g_variant_get(tmp_value, "s", &address);
685 G_VARIANT_UNREF(tmp_value);
687 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
688 g_variant_get(tmp_value, "s", &name);
689 G_VARIANT_UNREF(tmp_value);
691 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
692 g_variant_get(tmp_value, "u", &device_class);
693 G_VARIANT_UNREF(tmp_value);
696 name = g_strdup(address);
698 if (headed_plugin_info->plugin_headed_enabled) {
699 unsigned char auth_info[5] = {0, };
701 DBG("LAUNCH SYSPOPUP");
702 DBG("Name [%s]", name);
703 DBG("Passkey [%s]", str_passkey);
705 __bt_hal_get_auth_info(reply, (char *)auth_info);
706 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST,
707 name, address, auth_info, str_passkey, NULL,
708 _gap_agent_get_path(agent));
710 DBG("Headless Confirmation");
712 if (TIZEN_FEATURE_BLUEZ_SPEAKER_REFERENCE) {
713 /* Reply the ssp confirmation automaticaly */
714 gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
717 if (TIZEN_FEATURE_ROBOT_REFERENCE) {
718 DBG("Robot Device. Auto Accept");
719 /* Reply the ssp confirmation automaticaly */
720 gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
723 __bt_hal_send_ssp_request_events(address, name, passkey,
724 device_class, BT_SSP_VARIANT_PASSKEY_CONFIRMATION);
730 g_variant_unref(reply);
731 g_variant_unref(reply_temp);
732 __bt_hal_agent_release_memory();
737 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
740 gchar *address = NULL;
744 GVariant *reply = NULL;
745 GVariant *reply_temp = NULL;
746 GVariant *tmp_value = NULL;
747 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
748 bt_hal_agent_osp_server_t *osp_server;
751 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
752 if (reply_temp == NULL) {
753 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
757 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
759 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
760 g_variant_get(tmp_value, "s", &address);
761 G_VARIANT_UNREF(tmp_value);
763 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
767 tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
768 g_variant_get(tmp_value, "s", &name);
769 G_VARIANT_UNREF(tmp_value);
771 name = g_strdup(address);
773 tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
774 g_variant_get(tmp_value, "b", &trust);
775 G_VARIANT_UNREF(tmp_value);
777 tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
778 g_variant_get(tmp_value, "b", &paired);
779 G_VARIANT_UNREF(tmp_value);
780 if ((paired == FALSE) && (trust == FALSE)) {
781 ERR("No paired & No trusted device");
782 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
786 INFO("Authorization request for device [%s] Service:[%s]\n", address + 12, uuid);
789 DBG("Trusted device, so authorize\n");
790 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
794 if (!strcasecmp(uuid, BT_HAL_HID_UUID)) {
795 gboolean is_connectable = __bt_hal_is_hid_device_connectable();
796 DBG("Automatically %s authorization for HID",
797 is_connectable ? "accept" : "reject");
798 if (is_connectable == TRUE)
799 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
801 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
805 if (!strcasecmp(uuid, BT_HAL_HFP_AUDIO_GATEWAY_UUID) ||
806 !strcasecmp(uuid, BT_HAL_HSP_AUDIO_GATEWAY_UUID) ||
807 !strcasecmp(uuid, BT_HAL_HFP_HF_UUID) ||
808 !strcasecmp(uuid, BT_HAL_HSP_HS_UUID) ||
809 !strcasecmp(uuid, BT_HAL_A2DP_PROFILE_UUID) ||
810 !strcasecmp(uuid, BT_HAL_HID_DEVICE_UUID) ||
811 !strcasecmp(uuid, BT_HAL_SAP_UUID_OLD) ||
812 !strcasecmp(uuid, BT_HAL_SAP_UUID_NEW) ||
814 !strcasecmp(uuid, BT_HAL_IOTIVITY_UUID) ||
816 !strcasecmp(uuid, BT_HAL_AVRCP_TARGET_UUID)) {
817 __bt_hal_send_authorize_request_event(address, uuid);
822 if (!strcasecmp(uuid, BT_HAL_OPP_UUID)) {
823 if (NULL != _bt_hal_gap_agent_find_osp_server_by_type(
824 agent->osp_servers, BT_OSP_SERVER_OBEX, NULL)) {
825 INFO("OSP server for OPP found, send event");
826 __bt_hal_send_authorize_request_event(address, uuid);
829 INFO("Native OPP server, auto accept");
830 gap_agent_reply_authorize(agent,
831 GAP_AGENT_ACCEPT, NULL);
836 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
837 /* If user only listens(without accepts) to rfcomm server, occurs connection requested cb not popup */
838 osp_server = _bt_hal_gap_agent_find_osp_server_by_type(agent->osp_servers, BT_OSP_SERVER_RFCOMM, uuid);
840 INFO("Found rfcomm osp server. path: %s, fd: %d", osp_server->path, osp_server->fd);
841 __bt_hal_send_rfcomm_authorize_request_event(address, uuid, name, osp_server->path, osp_server->fd);
845 if (_is_rfcomm_server_uuid(uuid)) {
846 __bt_hal_send_rfcomm_authorize_request_event(address, uuid, NULL, NULL, -1);
852 if (_is_l2cap_le_server_uuid(uuid)) {
853 INFO("sending l2cap_le event for authorization");
854 /* Here, it is a custom uuid of the form "FFFFFFFF-FFFF-FFFF-FFFF-<psm in 12 digits>".
855 * It will be used in FRWK-API layer to extract psm from it.
857 __bt_hal_send_rfcomm_authorize_request_event(address, uuid, NULL, NULL, -1);
861 if (trust || !headed_plugin_info->plugin_headed_enabled) {
862 INFO("Trusted or Headless device, so authorize\n");
863 gap_agent_reply_authorize(agent,
864 GAP_AGENT_ACCEPT, NULL);
869 if (headed_plugin_info->plugin_headed_enabled) {
870 unsigned char auth_info[5] = {0, };
871 int request_type = BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST;
873 __bt_hal_get_auth_info(reply, (char *)auth_info);
875 if (!strcasecmp(uuid, BT_HAL_OPP_UUID))
876 request_type = BT_HAL_AGENT_EVENT_EXCHANGE_REQUEST;
877 else if (!strcasecmp(uuid, BT_HAL_PBAP_UUID))
878 request_type = BT_HAL_AGENT_EVENT_PBAP_REQUEST;
879 else if (!strcasecmp(uuid, BT_HAL_MAP_UUID))
880 request_type = BT_HAL_AGENT_EVENT_MAP_REQUEST;
882 headed_plugin_info->headed_plugin->bt_launch_system_popup(request_type, name,
883 address, auth_info, NULL, NULL, _gap_agent_get_path(agent));
889 g_variant_unref(reply);
890 g_variant_unref(reply_temp);
891 __bt_hal_agent_release_memory();
896 static gboolean __bt_hal_authorize_cancel_request(GapAgentPrivate *agent,
899 DBG("On Going Authorization is cancelled by remote [%s]", address);
900 gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
902 if (headed_plugin_info->plugin_headed_enabled)
903 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
905 __bt_hal_agent_release_memory();
909 static gboolean __bt_hal_pairing_cancel_request(GapAgentPrivate *agent, const char *address)
911 DBG("On Going Pairing is cancelled by remote [%s]", address);
913 if (headed_plugin_info->plugin_headed_enabled)
914 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
916 __bt_hal_agent_release_memory();
920 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class)
922 switch ((dev_class & 0x1f00) >> 8) {
924 switch ((dev_class & 0xc0) >> 6) {
926 /* input-keyboard" */
935 static gboolean __bt_hal_is_hid_device_connectable(void)
937 GDBusProxy *proxy = NULL;
938 GVariant *reply = NULL;
940 gboolean connectable = FALSE;
942 proxy = _bt_hal_get_hid_agent_proxy();
946 reply = g_dbus_proxy_call_sync(proxy, "IsHidConnectable", NULL,
947 G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &err);
949 ERR("Error returned in method call");
951 ERR("Error message = %s", err->message);
956 g_variant_get(reply, "(b)", &connectable);
957 g_variant_unref(reply);
959 g_object_unref(proxy);
961 INFO("HID Device is %s",
962 connectable ? "Connectable" : "Non-connectable");
967 static int __bt_hal_device_generate_passkey(char *passkey, int size)
972 unsigned int value = 0;
980 random_fd = open("/dev/urandom", O_RDONLY);
985 for (i = 0; i < size; i++) {
986 len = read(random_fd, &value, sizeof(value));
988 passkey[i] = '0' + (value % 10);
993 DBG("passkey: %s", passkey);
998 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
1004 pch = strtok_r(buffer, "= ,", &last);
1009 while ((pch = strtok_r(NULL, ",", &last))) {
1010 if (0 == g_strcmp0(pch, address)) {
1011 DBG("Match found\n");
1018 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
1019 const char *partial_name)
1024 pch = strtok_r(buffer, "= ,", &last);
1029 while ((pch = strtok_r(NULL, ",", &last))) {
1030 if (g_str_has_prefix(partial_name, pch)) {
1031 DBG("Match found\n");
1038 static gboolean __bt_hal_device_is_device_blacklisted(const char *address,
1050 fp = fopen(BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
1053 ERR("Unable to open blacklist file");
1057 fseek(fp, 0, SEEK_END);
1060 DBG("size is not a positive number");
1067 buffer = g_malloc0(sizeof(char) * size);
1068 /* Fix : NULL_RETURNS */
1069 if (buffer == NULL) {
1070 ERR("Fail to allocate memory");
1074 result = fread((char *)buffer, 1, size, fp);
1076 if (result != size) {
1082 lines = g_strsplit_set(buffer, BT_HAL_AGENT_NEW_LINE, 0);
1085 if (lines == NULL) {
1086 ERR("No lines in the file");
1090 for (i = 0; lines[i] != NULL; i++) {
1091 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
1092 if (__bt_hal_find_device_by_address_exactname(
1095 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
1096 if (__bt_hal_find_device_by_address_exactname(
1099 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
1100 if (__bt_hal_find_device_by_partial_name(lines[i],
1103 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
1104 if (__bt_hal_find_device_by_address_exactname(
1112 DBG("Found the device");
1117 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
1118 const gchar *address, const gchar *name)
1120 gboolean is_headset = FALSE;
1121 gboolean is_mouse = FALSE;
1122 unsigned int adapter_class = 0;
1123 char lap_address[BT_HAL_LOWER_ADDRESS_LENGTH];
1125 DBG("bt_agent_is_headset_class, %d +", dev_class);
1127 if (address == NULL)
1130 _bt_hal_dbus_get_adapter_class(&adapter_class);
1132 if (((adapter_class & 0x1f00) >> 8) == 0x05)
1134 DBG("Adapter is Peripheral, do not response automatically");
1138 switch ((dev_class & 0x1f00) >> 8) {
1140 switch ((dev_class & 0xfc) >> 2) {
1150 case 0x0b: /* VCR */
1151 case 0x0c: /* Video Camera */
1152 case 0x0d: /* Camcorder */
1155 /* Other audio device */
1161 switch (dev_class & 0xff) {
1162 case 0x80: /* 0x80: Pointing device(Mouse) */
1166 case 0x40: /* 0x40: input device (BT keyboard) */
1168 /* Get the LAP(Lower Address part) */
1169 g_strlcpy(lap_address, address, sizeof(lap_address));
1171 /* Need to Auto pair the blacklisted Keyboard */
1172 if (__bt_hal_device_is_device_blacklisted(lap_address, name) != TRUE) {
1173 DBG("Device is not black listed\n");
1176 ERR("Device is black listed\n");
1182 if ((!is_headset) && (!is_mouse))
1185 /* Get the LAP(Lower Address part) */
1186 g_strlcpy(lap_address, address, sizeof(lap_address));
1188 DBG("Device address = %s\n", address);
1189 DBG("Address 3 byte = %s\n", lap_address);
1191 if (__bt_hal_device_is_device_blacklisted(lap_address, name)) {
1192 ERR("Device is black listed\n");
1199 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface)
1201 GError *error = NULL;
1204 reply = g_dbus_proxy_call_sync(device,
1205 "GetAll", g_variant_new("(s)", interface),
1206 G_DBUS_CALL_FLAGS_NONE, -1,
1208 if (reply == NULL) {
1209 ERR("GetAll dBUS-RPC failed");
1211 ERR("D-Bus API failure: errCode[%x], message[%s]",
1212 error->code, error->message);
1213 g_clear_error(&error);
1221 static void __bt_hal_agent_release_memory(void)
1223 /* Release Malloc Memory*/
1226 /* Release Stack Memory*/
1230 static inline void stack_trim(void)
1237 unsigned int stacktop;
1240 asm volatile ("mov %0,sp " : "=r"(sp));
1242 sprintf(buf, "/proc/%d/maps", getpid());
1243 file = fopen(buf, "r");
1244 while (fgets(buf, BUF_SIZE, file) != NULL) {
1245 if (strstr(buf, "[stack]")) {
1253 sscanf(buf, "%x-", &stacktop);
1254 if (madvise((void *)PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop,
1256 perror("stack madvise fail");