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.
26 #include <syspopup_caller.h>
29 #include <bundle_internal.h>
30 #include <eventsystem.h>
32 #include <dbus/dbus-glib.h>
33 #include <dbus/dbus.h>
46 #include "bt-hal-log.h"
47 #include "bt-hal-msg.h"
48 #include "bt-hal-internal.h"
49 #include "bt-hal-utils.h"
50 #include "bt-hal-event-receiver.h"
51 #include "bt-hal-dbus-common-utils.h"
53 #include "bt-hal-adapter-dbus-handler.h"
54 #include "bt-hal-event-receiver.h"
56 #include <bt-hal-agent.h>
57 #include <bt-hal-gap-agent.h>
58 #include <bt-hal-dbus-common-utils.h>
60 #define BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE (APP_SYSCONFDIR"/auto-pair-blacklist")
61 #define BT_HAL_AGENT_NEW_LINE "\r\n"
63 #define PAGE_SIZE (1 << 12)
64 #define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1)))
65 #define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
66 #define PAGE_ALIGN(addr) _ALIGN_DOWN(addr, PAGE_SIZE)
67 #define BT_HAL_PIN_MAX_LENGTH 16
68 #define BT_HAL_PASSKEY_MAX_LENGTH 4
69 #define BT_HAL_LOWER_ADDRESS_LENGTH 9
70 #define BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
71 #define BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT 3
73 #define G_VARIANT_UNREF(variant) \
74 g_variant_unref(variant); \
76 #define BT_HAL_MAX_EVENT_STR_LENGTH 50
78 static void *adapter_agent = NULL;
80 /* Forward delcaration */
81 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
83 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device);
84 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
86 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device);
87 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
89 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
91 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface);
92 static void __bt_hal_agent_release_memory(void);
93 static inline void stack_trim(void);
95 #ifdef TIZEN_SYSPOPUP_SUPPORTED
96 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class);
97 static int __bt_hal_device_generate_passkey(char *passkey, int size);
98 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
99 const gchar *address, const gchar *name);
100 static gboolean __bt_hal_device_is_device_blacklisted(const char *address, const char *name);
101 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
102 const char *address);
103 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
104 const char *partial_name);
105 static gboolean __bt_hal_agent_system_popup_timer_cb(gpointer user_data);
107 static void __bt_hal_send_ssp_request_events(const gchar *address, const gchar *name,
108 guint passkey, uint32_t cod, unsigned char variant);
109 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid);
112 void* _bt_hal_create_agent(const char *path, gboolean adapter)
114 GAP_AGENT_FUNC_CB func_cb;
115 GDBusProxy *adapter_proxy;
116 GapAgentPrivate *agent;
119 adapter_proxy = _bt_get_adapter_proxy();
123 func_cb.pincode_func = __bt_hal_pincode_request;
124 func_cb.display_func = __bt_hal_display_request;
125 func_cb.passkey_func = __bt_hal_passkey_request;
126 func_cb.confirm_func = __bt_hal_confirm_request;
127 func_cb.authorize_func = __bt_hal_authorize_request;
128 func_cb.pairing_cancel_func = NULL;
129 func_cb.authorization_cancel_func = NULL;
132 agent = g_new0(GapAgentPrivate, 1);
134 _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
137 if (!_gap_agent_register(agent)) {
138 ERR("gap agent registration failed!");
139 _bt_hal_destroy_agent(agent);
147 void _bt_hal_destroy_agent(void *agent)
153 _gap_agent_reset_dbus((GapAgentPrivate *)agent);
159 gboolean _bt_hal_agent_is_canceled(void)
161 void *agent = _bt_hal_get_adapter_agent();
165 return _gap_agent_is_canceled(agent);
168 int _bt_hal_agent_reply_cancellation(void)
170 void *agent = _bt_hal_get_adapter_agent();
172 return BT_STATUS_FAIL;
174 if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
175 ERR("Fail to reply agent");
176 return BT_STATUS_FAIL;
178 DBG("gap agent cancellation done successfully!");
179 return BT_STATUS_SUCCESS;
183 void _bt_hal_agent_set_canceled(gboolean value)
185 void *agent = _bt_hal_get_adapter_agent();
189 return _gap_agent_set_canceled(agent, value);
192 void _bt_hal_initialize_adapter_agent(void)
194 adapter_agent = _bt_hal_create_agent(BT_HAL_ADAPTER_AGENT_PATH, TRUE);
195 if (!adapter_agent) {
196 ERR("Fail to register agent");
201 void _bt_hal_destroy_adapter_agent(void)
204 _bt_hal_destroy_agent(adapter_agent);
205 adapter_agent = NULL;
208 void* _bt_hal_get_adapter_agent(void)
210 return adapter_agent;
213 #ifndef TIZEN_SYSPOPUP_SUPPORTED
214 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid)
216 struct hal_ev_authorize_request ev;
217 memset(&ev, 0, sizeof(ev));
219 DBG("Remote Device address [%s]", address);
221 _bt_convert_addr_string_to_type(ev.bdaddr, address);
222 ev.service_id = _bt_convert_uuid_string_to_service_id(uuid);
224 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
226 DBG("Sending AUTHORIZE REQUEST");
227 event_cb(HAL_EV_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
235 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
238 struct hal_ev_pin_request ev;
239 memset(&ev, 0, sizeof(ev));
241 DBG("Remote Device address [%s]", address);
242 DBG("Remote Device Name [%s]", name);
243 DBG("Remote Device COD [%u]", cod);
245 _bt_convert_addr_string_to_type(ev.bdaddr, address);
247 memcpy(ev.name, name, strlen(name));
248 ev.class_of_dev = cod;
250 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
252 DBG("Sending PIN REQUEST");
253 event_cb(HAL_EV_PIN_REQUEST, (void*)&ev, sizeof(ev));
259 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
261 uint32_t device_class;
262 const gchar *address;
264 GVariant *reply = NULL;
265 GVariant *reply_temp = NULL;
269 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
271 if (reply_temp == NULL) {
272 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
277 g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
279 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
280 g_variant_get(tmp_value, "u", &device_class);
281 G_VARIANT_UNREF(tmp_value);
283 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
284 g_variant_get(tmp_value, "s", &address);
285 G_VARIANT_UNREF(tmp_value);
287 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
288 g_variant_get(tmp_value, "s", &name);
289 G_VARIANT_UNREF(tmp_value);
293 #ifdef TIZEN_SYSPOPUP_SUPPORTED
294 if (__bt_hal_device_is_hid_keyboard(device_class)) {
295 DBG("Device is HID Keyboard");
296 char str_passkey[BT_HAL_PASSKEY_MAX_LENGTH + 1] = { 0 };
297 if (__bt_hal_device_generate_passkey(str_passkey,
298 BT_HAL_PASSKEY_MAX_LENGTH) != 0) {
299 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
303 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
306 DBG("Launch BT Syspopup");
307 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
308 name, str_passkey, NULL,
309 _gap_agent_get_path(agent));
310 } else if (!__bt_hal_device_is_auto_response(device_class, address, name)) {
311 DBG("Device is not of AUto response class, Show PIN Entry");
312 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PIN_REQUEST, name, NULL,
313 NULL, _gap_agent_get_path(agent));
315 DBG("Device is of Type Auto response, send event to HAL");
316 __bt_hal_send_pin_request_event(address, name, device_class);
319 DBG("PIN CODE request, device class [%u]", device_class);
320 __bt_hal_send_pin_request_event(address, name, device_class);
324 g_variant_unref(reply);
325 g_variant_unref(reply_temp);
326 __bt_hal_agent_release_memory();
333 /* BT_SSP_VARIANT_PASSKEY_CONFIRMATION */
334 /* BT_SSP_VARIANT_PASSKEY_NOTIFICATION */
335 /* BT_SSP_VARIANT_PASSKEY_ENTRY */
336 /* BT_SSP_VARIANT_CONSENT */
338 #ifndef TIZEN_SYSPOPUP_SUPPORTED
339 static void __bt_hal_send_ssp_request_events(const gchar *address,
343 unsigned char variant)
345 struct hal_ev_ssp_request ev;
346 memset(&ev, 0, sizeof(ev));
347 DBG("sizeof ev [%d]", sizeof(ev));
349 DBG("Remote Device address [%s]", address);
350 DBG("Remote Device Name [%s]", name);
351 DBG("Remote Device passkey [%d]", passkey);
352 DBG("Remote Device pairing variant [0x%x]", variant);
353 DBG("Remote Device cod [%d]", cod);
355 _bt_convert_addr_string_to_type(ev.bdaddr, address);
357 memcpy(ev.name, name, strlen(name));
358 ev.class_of_dev = cod;
359 ev.pairing_variant = variant;
360 ev.passkey = passkey;
362 handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
364 DBG("Sending SSP type [%d]", variant);
365 event_cb(HAL_EV_SSP_REQUEST, (void*)&ev, sizeof(ev));
373 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
376 const gchar *address;
379 uint32_t device_class;
380 GVariant *reply = NULL;
381 GVariant *reply_temp = NULL;
382 GVariant *tmp_value = NULL;
385 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
386 if (reply_temp == NULL) {
387 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
392 g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
394 tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
395 g_variant_get(tmp_value, "s", &address);
396 G_VARIANT_UNREF(tmp_value);
398 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
402 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
403 g_variant_get(tmp_value, "s", &name);
404 G_VARIANT_UNREF(tmp_value);
406 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
407 g_variant_get(tmp_value, "u", &device_class);
408 G_VARIANT_UNREF(tmp_value);
413 str_passkey = g_strdup_printf("%d", passkey);
415 #ifdef TIZEN_SYSPOPUP_SUPPORTED
416 DBG("Launch BT Syspopup: KEYBOARD_PASSKEY_REQUEST");
417 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
419 _gap_agent_get_path(agent));
422 __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
423 BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
428 g_variant_unref(reply);
429 g_variant_unref(reply_temp);
430 __bt_hal_agent_release_memory();
437 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
439 const gchar *address;
441 uint32_t device_class;
442 GVariant *reply = NULL;
443 GVariant *reply_temp = NULL;
447 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
449 if (reply_temp == NULL) {
450 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
455 g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
457 tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
458 g_variant_get(tmp_value, "s", &address);
459 G_VARIANT_UNREF(tmp_value);
461 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
465 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
466 g_variant_get(tmp_value, "s", &name);
467 G_VARIANT_UNREF(tmp_value);
469 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
470 g_variant_get(tmp_value, "u", &device_class);
471 G_VARIANT_UNREF(tmp_value);
475 #ifdef TIZEN_SYSPOPUP_SUPPORTED
476 DBG("Launch BT Syspopup: PASSKEY_REQUEST");
477 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL,
478 _gap_agent_get_path(agent));
480 __bt_hal_send_ssp_request_events(address, name, 0, device_class,
481 BT_SSP_VARIANT_PASSKEY_ENTRY);
485 g_variant_unref(reply);
486 g_variant_unref(reply_temp);
487 __bt_hal_agent_release_memory();
494 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
497 const gchar *address;
500 uint32_t device_class;
501 GVariant *reply_temp = NULL;
502 GVariant *reply = NULL;
504 DBG("+ passkey[%.6d]", passkey);
505 DBG("Agent Path [%s]", agent->path);
507 snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
509 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
511 if (reply_temp == NULL) {
512 ERR("####Device doesn't exist####");
513 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
517 g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
519 tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
520 g_variant_get(tmp_value, "s", &address);
521 G_VARIANT_UNREF(tmp_value);
523 tmp_value = g_variant_lookup_value (reply, "Name", G_VARIANT_TYPE_STRING);
524 g_variant_get(tmp_value, "s", &name);
525 G_VARIANT_UNREF(tmp_value);
527 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
528 g_variant_get(tmp_value, "u", &device_class);
529 G_VARIANT_UNREF(tmp_value);
533 #ifdef TIZEN_WEARABLE
534 uint32_t major_class;
537 major_class = (device_class & 0x1f00) >> 8;
539 if (major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) {
540 DBG("Audio device. Launch passkey pop-up");
541 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
542 str_passkey, NULL, _gap_agent_get_path(agent));
546 if (__is_reset_required(address)) {
547 DBG("Launch system reset pop-up");
548 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_SYSTEM_RESET_REQUEST, name,
549 NULL, NULL, _gap_agent_get_path(agent));
551 DBG("Launch passkey pop-up");
552 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED, name,
553 str_passkey, NULL, _gap_agent_get_path(agent));
555 gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
559 #ifdef TIZEN_SYSPOPUP_SUPPORTED
560 DBG("Launch BT Syspopup");
561 DBG("Name [%s]", name);
562 DBG("Passkey [%s]", str_passkey);
563 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
565 _gap_agent_get_path(agent));
567 __bt_hal_send_ssp_request_events(address, name, passkey,
568 device_class, BT_SSP_VARIANT_PASSKEY_CONFIRMATION);
569 #endif //TIZEN_SYSPOPUP_SUPPORTED
570 #endif //TIZEN_WEARABLE
573 g_variant_unref(reply);
574 g_variant_unref(reply_temp);
575 __bt_hal_agent_release_memory();
580 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
583 const gchar *address;
587 GVariant *reply = NULL;
588 GVariant *reply_temp = NULL;
591 DBG("Authorize Request from Bluez Stack: UUID [%s]", uuid);
593 reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
594 if (reply_temp == NULL) {
595 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
599 g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
601 tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
602 g_variant_get(tmp_value, "s", &address);
603 G_VARIANT_UNREF(tmp_value);
605 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
609 tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
610 g_variant_get(tmp_value, "s", &name);
611 G_VARIANT_UNREF(tmp_value);
615 tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
616 g_variant_get(tmp_value, "b", &trust);
617 G_VARIANT_UNREF(tmp_value);
619 tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
620 g_variant_get(tmp_value, "b", &paired);
621 G_VARIANT_UNREF(tmp_value);
622 if ((paired == FALSE) && (trust == FALSE)) {
623 ERR("No paired & No trusted device");
624 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
628 INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
631 INFO("Trusted device, so authorize\n");
632 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
635 INFO("Device is not Trusted, so prompt user to accept or reject authorization \n");
639 * TODO: Handling for authorization request for different profiles will be
640 * implemented while profiles support is added. For now send all the request
641 * to bt-service or, launch bt-syspopup.
643 #ifdef TIZEN_SYSPOPUP_SUPPORTED
644 DBG("Launch Syspopup: AUTHORIZE_REQUEST");
645 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST,
646 name, NULL, NULL, _gap_agent_get_path(agent));
648 __bt_hal_send_authorize_request_event(address, uuid);
652 g_variant_unref(reply);
653 g_variant_unref(reply_temp);
654 __bt_hal_agent_release_memory();
660 #ifdef TIZEN_SYSPOPUP_SUPPORTED
661 int _bt_hal_launch_system_popup(bt_hal_agent_event_type_t event_type,
662 const char *device_name,
664 const char *filename,
665 const char *agent_path)
669 char event_str[BT_HAL_MAX_EVENT_STR_LENGTH + 1];
674 DBG("Launching system popup failed");
678 bundle_add(b, "device-name", device_name);
679 bundle_add(b, "passkey", passkey);
680 bundle_add(b, "file", filename);
681 bundle_add(b, "agent-path", agent_path);
683 switch (event_type) {
684 case BT_HAL_AGENT_EVENT_PIN_REQUEST:
685 g_strlcpy(event_str, "pin-request", sizeof(event_str));
688 case BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
689 g_strlcpy(event_str, "passkey-confirm-request",
693 case BT_HAL_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED:
694 g_strlcpy(event_str, "passkey-auto-accepted",
698 case BT_HAL_AGENT_EVENT_PASSKEY_REQUEST:
699 g_strlcpy(event_str, "passkey-request", sizeof(event_str));
702 case BT_HAL_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
703 g_strlcpy(event_str, "passkey-display-request",
705 case BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST:
706 g_strlcpy(event_str, "authorize-request",
710 case BT_HAL_AGENT_EVENT_CONFIRM_MODE_REQUEST:
711 g_strlcpy(event_str, "confirm-mode-request",
715 case BT_HAL_AGENT_EVENT_FILE_RECEIVED:
716 g_strlcpy(event_str, "file-received", sizeof(event_str));
719 case BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
720 g_strlcpy(event_str, "keyboard-passkey-request",
724 case BT_HAL_AGENT_EVENT_TERMINATE:
725 g_strlcpy(event_str, "terminate", sizeof(event_str));
728 case BT_HAL_AGENT_EVENT_EXCHANGE_REQUEST:
729 g_strlcpy(event_str, "exchange-request", sizeof(event_str));
732 case BT_HAL_AGENT_EVENT_PBAP_REQUEST:
733 g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
736 case BT_HAL_AGENT_EVENT_MAP_REQUEST:
737 g_strlcpy(event_str, "message-request", sizeof(event_str));
739 #ifdef TIZEN_WEARABLE
740 case BT_HAL_AGENT_EVENT_SYSTEM_RESET_REQUEST:
741 __bt_register_popup_event_signal();
742 g_strlcpy(event_str, "system-reset-request", sizeof(event_str));
746 case BT_HAL_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE:
747 g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str));
751 DBG("Invalid event type");
757 bundle_add(b, "event-type", event_str);
759 ret = syspopup_launch("bt-syspopup", b);
761 DBG("Popup launch failed...retry %d", ret);
763 g_timeout_add(BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
764 (GSourceFunc)__bt_hal_agent_system_popup_timer_cb, b);
769 DBG("_bt_agent_launch_system_popup");
773 static gboolean __bt_hal_agent_system_popup_timer_cb(gpointer user_data)
776 static int retry_count;
777 bundle *b = (bundle *)user_data;
778 if (user_data == NULL)
783 ret = syspopup_launch("bt-syspopup", b);
785 DBG("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..",
787 if (retry_count >= BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT) {
788 DBG("Sorry!! Max retry %d reached", retry_count);
794 DBG("Hurray!! Finally Popup launched");
799 return (ret < 0) ? TRUE : FALSE;
802 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class)
804 switch ((dev_class & 0x1f00) >> 8) {
806 switch ((dev_class & 0xc0) >> 6) {
808 /* input-keyboard" */
817 static int __bt_hal_device_generate_passkey(char *passkey, int size)
822 unsigned int value = 0;
830 random_fd = open("/dev/urandom", O_RDONLY);
835 for (i = 0; i < size; i++) {
836 len = read(random_fd, &value, sizeof(value));
838 passkey[i] = '0' + (value % 10);
843 DBG("passkey: %s", passkey);
848 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
854 pch = strtok_r(buffer, "= ,", &last);
859 while ((pch = strtok_r(NULL, ",", &last))) {
860 if (0 == g_strcmp0(pch, address)) {
861 DBG("Match found\n");
868 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
869 const char *partial_name)
874 pch = strtok_r(buffer, "= ,", &last);
879 while ((pch = strtok_r(NULL, ",", &last))) {
880 if (g_str_has_prefix(partial_name, pch)) {
881 DBG("Match found\n");
888 static gboolean __bt_hal_device_is_device_blacklisted(const char *address,
900 fp = fopen(BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
903 ERR("Unable to open blacklist file");
907 fseek(fp, 0, SEEK_END);
910 DBG("size is not a positive number");
917 buffer = g_malloc0(sizeof(char) * size);
918 /* Fix : NULL_RETURNS */
919 if (buffer == NULL) {
920 ERR("Fail to allocate memory");
924 result = fread((char *)buffer, 1, size, fp);
926 if (result != size) {
932 DBG("Buffer = %s", buffer);
934 lines = g_strsplit_set(buffer, BT_HAL_AGENT_NEW_LINE, 0);
938 ERR("No lines in the file");
942 for (i = 0; lines[i] != NULL; i++) {
943 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
944 if (__bt_hal_find_device_by_address_exactname(
947 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
948 if (__bt_hal_find_device_by_address_exactname(
951 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
952 if (__bt_hal_find_device_by_partial_name(lines[i],
955 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
956 if (__bt_hal_find_device_by_address_exactname(
964 DBG("Found the device");
969 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
970 const gchar *address, const gchar *name)
972 gboolean is_headset = FALSE;
973 gboolean is_mouse = FALSE;
974 char lap_address[BT_HAL_LOWER_ADDRESS_LENGTH];
976 DBG("bt_agent_is_headset_class, %d +", dev_class);
981 switch ((dev_class & 0x1f00) >> 8) {
983 switch ((dev_class & 0xfc) >> 2) {
994 case 0x0c: /* Video Camera */
995 case 0x0d: /* Camcorder */
998 /* Other audio device */
1004 switch (dev_class & 0xff) {
1005 case 0x80: /* 0x80: Pointing device(Mouse) */
1009 case 0x40: /* 0x40: input device (BT keyboard) */
1011 /* Get the LAP(Lower Address part) */
1012 g_strlcpy(lap_address, address, sizeof(lap_address));
1014 /* Need to Auto pair the blacklisted Keyboard */
1015 if (__bt_hal_device_is_device_blacklisted(lap_address, name) != TRUE) {
1016 DBG("Device is not black listed\n");
1019 ERR("Device is black listed\n");
1025 if ((!is_headset) && (!is_mouse))
1028 /* Get the LAP(Lower Address part) */
1029 g_strlcpy(lap_address, address, sizeof(lap_address));
1031 DBG("Device address = %s\n", address);
1032 DBG("Address 3 byte = %s\n", lap_address);
1034 if (__bt_hal_device_is_device_blacklisted(lap_address, name)) {
1035 ERR("Device is black listed\n");
1043 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface)
1045 GError *error = NULL;
1048 reply = g_dbus_proxy_call_sync(device,
1049 "GetAll", g_variant_new("(s)", interface),
1050 G_DBUS_CALL_FLAGS_NONE, -1,
1052 if (reply == NULL) {
1053 ERR("GetAll dBUS-RPC failed");
1055 ERR("D-Bus API failure: errCode[%x], message[%s]",
1056 error->code, error->message);
1057 g_clear_error(&error);
1066 static void __bt_hal_agent_release_memory(void)
1068 /* Release Malloc Memory*/
1071 /* Release Stack Memory*/
1075 static inline void stack_trim(void)
1081 unsigned int stacktop;
1084 asm volatile ("mov %0,sp " : "=r"(sp));
1086 sprintf(buf, "/proc/%d/maps", getpid());
1087 file = fopen(buf, "r");
1088 while (fgets(buf, BUF_SIZE, file) != NULL) {
1089 if (strstr(buf, "[stack]")) {
1097 sscanf(buf, "%x-", &stacktop);
1098 if (madvise((void *)PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop,
1100 perror("stack madvise fail");