3.0 specific patch: enable to build after tizen 2.4 code sync.
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-agent.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <string.h>
27 #include <malloc.h>
28 #include <stacktrim.h>
29
30 #if defined(LIBNOTIFY_SUPPORT)
31 #include "bt-popup.h"
32 #elif defined(LIBNOTIFICATION_SUPPORT)
33 #include "bt-service-agent-notification.h"
34 #else
35 #include <syspopup_caller.h>
36 #endif
37
38 #include <vconf.h>
39 #include <bundle_internal.h>
40
41 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
42 #include <tethering.h>
43 #endif
44
45 #include "bt-internal-types.h"
46 #include "bt-service-common.h"
47 #include "bt-service-agent.h"
48 #include "bt-service-gap-agent.h"
49 #include "bt-service-adapter.h"
50 #include "bt-service-event.h"
51 #include "bt-service-rfcomm-server.h"
52 #include "bt-service-device.h"
53 #include "bt-service-audio.h"
54
55 #define BT_APP_AUTHENTICATION_TIMEOUT           35
56 #define BT_APP_AUTHORIZATION_TIMEOUT            15
57
58 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
59 #define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
60 #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
61 #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
62 #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
63 #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
64 #define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
65 #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb"
66 #define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb"
67 #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
68 #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
69 #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb"
70 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
71 #define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00"
72 #define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a"
73
74 #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent"
75
76 #define BT_AGENT_INTERFACE "org.bluez.Agent1"
77
78 #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
79 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
80
81 #define BT_PIN_MAX_LENGTH 16
82 #define BT_PASSKEY_MAX_LENGTH 4
83
84 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
85 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
86 #define BT_PAN_MAX_CONNECTION 4
87 extern guint nap_connected_device_count;
88
89 #define G_VARIANT_UNREF(variant) \
90         g_variant_unref(variant); \
91         variant = NULL
92
93 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
94                                                         const gchar *name);
95 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
96 static int __bt_agent_generate_passkey(char *passkey, int size);
97
98 static void __bt_agent_release_memory(void)
99 {
100         /* Release Malloc Memory*/
101         malloc_trim(0);
102
103         /* Release Stack Memory*/
104         stack_trim();
105 }
106
107 static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data)
108 {
109         int ret;
110         static int retry_count;
111         bundle *b = (bundle *)user_data;
112         retv_if(user_data == NULL, FALSE);
113
114         ++retry_count;
115 #if defined(LIBNOTIFY_SUPPORT)
116         ret = notify_launch(b);
117 #elif defined(LIBNOTIFICATION_SUPPORT)
118         ret = notification_launch(b);
119 #else
120         ret = syspopup_launch("bt-syspopup", b);
121 #endif
122         if (ret < 0) {
123                 BT_ERR("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..",
124                                                         ret, retry_count);
125                 if (retry_count >= BT_AGENT_SYSPOPUP_MAX_ATTEMPT) {
126                         BT_ERR("Sorry!! Max retry %d reached", retry_count);
127                         bundle_free(b);
128                         retry_count = 0;
129                         return FALSE;
130                 }
131         } else {
132                 BT_DBG("Hurray!! Finally Popup launched");
133                 retry_count = 0;
134                 bundle_free(b);
135         }
136
137         return (ret < 0) ? TRUE : FALSE;
138 }
139
140 #ifdef TIZEN_WEARABLE
141 static void __bt_unbond_cb(GDBusProxy *proxy,
142                 GAsyncResult *res, gpointer user_data)
143 {
144         GError *err = NULL;
145         GVariant *value;
146
147         value = g_dbus_proxy_call_finish(proxy, res, &err);
148         if (value == NULL) {
149                 BT_ERR("Error: Unbond Failed");
150                 if (err) {
151                         BT_ERR("errCode[%x], message[%s]\n", err->code, err->message);
152                         g_clear_error(&err);
153                 }
154                 return;
155         }
156         g_variant_unref(value);
157         BT_INFO("Unbonding is done");
158         return;
159 }
160
161 static gboolean __bt_unpair_device(void)
162 {
163         GArray *device_list;
164         int no_of_device;
165         int i;
166
167         device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
168         if (device_list == NULL) {
169                 BT_ERR("g_array_new is failed");
170                 return FALSE;
171         }
172
173         if (_bt_get_bonded_devices(&device_list) != BLUETOOTH_ERROR_NONE) {
174                 BT_ERR("_bt_get_bonded_devices is failed");
175                 g_array_free(device_list, TRUE);
176                 return FALSE;
177         }
178
179         no_of_device = device_list->len / sizeof(bluetooth_device_info_t);
180         for (i = 0; i < no_of_device; i++) {
181                 GDBusProxy *adapter_proxy;
182                 bluetooth_device_info_t info;
183                 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
184                 char *device_path = NULL;
185
186                 info = g_array_index(device_list, bluetooth_device_info_t, i);
187                 if (info.device_class.major_class ==
188                                 BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO)
189                         continue;
190
191                 adapter_proxy = _bt_get_adapter_proxy();
192                 if (!adapter_proxy) {
193                         BT_ERR("adapter_proxy is NULL");
194                         g_array_free(device_list, TRUE);
195                         return FALSE;
196                 }
197
198                 _bt_convert_addr_type_to_string(addr, info.device_address.addr);
199                 device_path = _bt_get_device_object_path(addr);
200                 if (device_path == NULL) {
201                         BT_ERR("device_path is NULL");
202                         g_array_free(device_list, TRUE);
203                         return FALSE;
204                 }
205
206                 g_dbus_proxy_call(adapter_proxy,
207                                 "UnpairDevice", g_variant_new("o", device_path),
208                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
209                                 (GAsyncReadyCallback)__bt_unbond_cb, NULL);
210
211                 BT_INFO("unbonding %s is requested", addr);
212
213                 g_array_free(device_list, TRUE);
214                 return TRUE;
215         }
216
217         g_array_free(device_list, TRUE);
218         return FALSE;
219 }
220
221 static void __bt_popup_event_filter(GDBusConnection *connection,
222                 const gchar *sender_name,
223                 const gchar *object_path,
224                 const gchar *interface_name,
225                 const gchar *signal_name,
226                 GVariant *parameters,
227                 gpointer user_data)
228 {
229         BT_DBG("Sender Name[%s] Object Path[%s] Interface[%s] Signal[%s]",
230                         sender_name, object_path, interface_name, signal_name);
231
232         if (g_strcmp0(interface_name, "User.Bluetooth.syspopup") == 0 &&
233                         g_strcmp0(signal_name, "ResetResponse") == 0) {
234                 int response;
235
236                 g_variant_get(parameters, "(i)", &response);
237                 BT_DBG("response = %d", response);
238         }
239 }
240
241 int __bt_service_subscribe_popup(GDBusConnection *conn,
242                 gboolean subscribe)
243 {
244         static guint subs_interface_added_id = 0;
245
246         if (conn == NULL)
247                 return BLUETOOTH_ERROR_INVALID_PARAM;
248
249         if (subscribe) {
250                 if (subs_interface_added_id == 0) {
251                         subs_interface_added_id = g_dbus_connection_signal_subscribe(conn,
252                                         NULL, "User.Bluetooth.syspopup", "ResetResponse", NULL, NULL, 0,
253                                         __bt_popup_event_filter, NULL, NULL);
254                 }
255         } else {
256                 if (subs_interface_added_id > 0) {
257                         g_dbus_connection_signal_unsubscribe(conn,
258                                         subs_interface_added_id);
259                         subs_interface_added_id = 0;
260                 }
261         }
262         return BLUETOOTH_ERROR_NONE;
263 }
264
265 static void  __bt_register_popup_event_signal(void)
266 {
267         GDBusConnection *conn;
268
269         BT_DBG("+\n");
270
271         conn = _bt_get_system_gconn();
272         if (conn == NULL)
273                 return;
274
275         __bt_service_subscribe_popup(conn, TRUE);
276
277         BT_DBG("-\n");
278         return;
279 }
280
281 static gboolean __is_reset_required(const gchar *address)
282 {
283         GArray *device_list;
284         uint32_t no_of_device;
285         uint32_t i;
286         bluetooth_device_info_t info;
287         gboolean is_required = FALSE;
288
289         device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
290         if (device_list == NULL) {
291                 BT_ERR("g_array_new is failed");
292                 return FALSE;
293         }
294
295         if (_bt_get_bonded_devices(&device_list) != BLUETOOTH_ERROR_NONE) {
296                 BT_ERR("_bt_get_bonded_devices is failed");
297                 g_array_free(device_list, TRUE);
298                 return FALSE;
299         }
300
301         no_of_device = device_list->len / sizeof(bluetooth_device_info_t);
302         for (i = 0; i < no_of_device; i++) {
303                 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
304
305                 info = g_array_index(device_list, bluetooth_device_info_t, i);
306
307                 _bt_convert_addr_type_to_string(addr, info.device_address.addr);
308                 if (g_strcmp0(address, addr) == 0) {
309                         BT_DBG("This device is already in paired list");
310                         is_required = FALSE;
311                         break;
312                 }
313
314                 if (info.device_class.major_class != BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) {
315                         is_required = TRUE;
316                         break;
317                 }
318         }
319         g_array_free(device_list, TRUE);
320
321         return is_required;
322 }
323 #endif
324
325 int _bt_launch_system_popup(bt_agent_event_type_t event_type,
326                                                         const char *device_name,
327                                                         char *passkey,
328                                                         const char *filename,
329                                                         const char *agent_path)
330 {
331         int ret;
332         bundle *b;
333         char event_str[BT_MAX_EVENT_STR_LENGTH + 1];
334
335         b = bundle_create();
336         if (!b) {
337                 BT_ERR("Launching system popup failed");
338                 return -1;
339         }
340
341         bundle_add(b, "device-name", device_name);
342         bundle_add(b, "passkey", passkey);
343         bundle_add(b, "file", filename);
344         bundle_add(b, "agent-path", agent_path);
345
346         switch (event_type) {
347         case BT_AGENT_EVENT_PIN_REQUEST:
348                 g_strlcpy(event_str, "pin-request", sizeof(event_str));
349                 break;
350
351         case BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
352                 g_strlcpy(event_str, "passkey-confirm-request",
353                                                 sizeof(event_str));
354                 break;
355
356         case BT_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED:
357                 g_strlcpy(event_str, "passkey-auto-accepted",
358                                                 sizeof(event_str));
359                 break;
360
361         case BT_AGENT_EVENT_PASSKEY_REQUEST:
362                 g_strlcpy(event_str, "passkey-request", sizeof(event_str));
363                 break;
364
365         case BT_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
366                 g_strlcpy(event_str, "passkey-display-request",
367                                                 sizeof(event_str));
368                 break;
369
370         case BT_AGENT_EVENT_AUTHORIZE_REQUEST:
371                 g_strlcpy(event_str, "authorize-request",
372                                                 sizeof(event_str));
373                 break;
374
375         case BT_AGENT_EVENT_CONFIRM_MODE_REQUEST:
376                 g_strlcpy(event_str, "confirm-mode-request",
377                                                 sizeof(event_str));
378                 break;
379
380         case BT_AGENT_EVENT_FILE_RECEIVED:
381                 g_strlcpy(event_str, "file-received", sizeof(event_str));
382                 break;
383
384         case BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
385                 g_strlcpy(event_str, "keyboard-passkey-request",
386                                                 sizeof(event_str));
387                 break;
388
389         case BT_AGENT_EVENT_TERMINATE:
390                 g_strlcpy(event_str, "terminate", sizeof(event_str));
391                 break;
392
393         case BT_AGENT_EVENT_EXCHANGE_REQUEST:
394                 g_strlcpy(event_str, "exchange-request", sizeof(event_str));
395                 break;
396
397         case BT_AGENT_EVENT_PBAP_REQUEST:
398                 g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
399                 break;
400
401         case BT_AGENT_EVENT_MAP_REQUEST:
402                 g_strlcpy(event_str, "message-request", sizeof(event_str));
403                 break;
404
405 #ifdef TIZEN_WEARABLE
406         case BT_AGENT_EVENT_SYSTEM_RESET_REQUEST:
407                 __bt_register_popup_event_signal();
408                 g_strlcpy(event_str, "system-reset-request", sizeof(event_str));
409                 break;
410 #endif
411
412         case BT_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE:
413                 g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str));
414                 break;
415
416         default:
417                 BT_ERR("Invalid event type");
418                 bundle_free(b);
419                 return -1;
420
421         }
422
423         bundle_add(b, "event-type", event_str);
424
425 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
426         ret = syspopup_launch("bt-syspopup", b);
427 #endif
428         if (0 > ret) {
429                 BT_ERR("Popup launch failed...retry %d", ret);
430
431                 g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
432                               (GSourceFunc)__bt_agent_system_popup_timer_cb, b);
433         } else {
434                 bundle_free(b);
435         }
436
437         BT_INFO("_bt_agent_launch_system_popup");
438         return 0;
439 }
440
441 static GVariant *__bt_service_getall(GDBusProxy *device, const char *interface)
442 {
443         GError *error = NULL;
444         GVariant *reply;
445
446         reply = g_dbus_proxy_call_sync(device,
447                         "GetAll", g_variant_new("(s)", interface),
448                         G_DBUS_CALL_FLAGS_NONE, -1,
449                         NULL, &error);
450         if (reply == NULL) {
451                 ERR("GetAll dBUS-RPC failed");
452                 if (error) {
453                         ERR("D-Bus API failure: errCode[%x], message[%s]",
454                                 error->code, error->message);
455                         g_clear_error(&error);
456                 }
457                 return NULL;
458         }
459
460         return reply;
461 }
462
463 static gboolean __pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
464 {
465         uint32_t device_class;
466         const gchar *address;
467         const gchar *name;
468         GVariant *reply = NULL;
469         GVariant *reply_temp = NULL;
470         GVariant *tmp_value;
471
472         BT_DBG("+");
473
474         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
475
476         if (reply_temp == NULL) {
477                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
478                                 NULL);
479                 goto done;
480         }
481
482         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
483
484         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
485         g_variant_get(tmp_value, "u", &device_class);
486         G_VARIANT_UNREF(tmp_value);
487
488         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
489         g_variant_get(tmp_value, "s", &address);
490         G_VARIANT_UNREF(tmp_value);
491         if (!address) {
492                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
493                 goto done;
494         }
495
496         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
497         g_variant_get(tmp_value, "s", &name);
498         G_VARIANT_UNREF(tmp_value);
499         if (!name)
500                 name = address;
501
502         if (_bt_is_device_creating() == TRUE &&
503                 _bt_is_bonding_device_address(address) == TRUE &&
504                 __bt_agent_is_auto_response(device_class, address, name)) {
505                 BT_DBG("0000 Auto Pair");
506                 /* Use Fixed PIN "0000" for basic pairing */
507                 _bt_set_autopair_status_in_bonding_info(TRUE);
508                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
509                                                                         NULL);
510         } else if (__bt_agent_is_hid_keyboard(device_class)) {
511                 BT_DBG("HID Keyboard");
512                 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
513
514                 if (__bt_agent_generate_passkey(str_passkey,
515                                         BT_PASSKEY_MAX_LENGTH) != 0) {
516                         gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
517                                                 "", NULL);
518                         goto done;
519                 }
520
521                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
522                                                         str_passkey, NULL);
523
524                 _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
525                                                 name, str_passkey, NULL,
526                                                 _gap_agent_get_path(agent));
527         } else {
528                 BT_DBG("Show Pin entry");
529                 _bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, NULL,
530                                         NULL, _gap_agent_get_path(agent));
531         }
532
533 done:
534         g_variant_unref(reply);
535         g_variant_unref(reply_temp);
536         __bt_agent_release_memory();
537         BT_DBG("-");
538
539         return TRUE;
540 }
541
542 static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
543 {
544         const gchar *address;
545         const gchar *name;
546         GVariant *reply = NULL;
547         GVariant *reply_temp = NULL;
548         GVariant *tmp_value;
549         BT_DBG("+");
550
551         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
552
553         if (reply_temp == NULL) {
554                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
555                                              NULL);
556                 goto done;
557         }
558
559         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
560
561         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
562         g_variant_get(tmp_value, "s", &address);
563         G_VARIANT_UNREF(tmp_value);
564         if (!address) {
565                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
566                 goto done;
567         }
568
569         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
570         g_variant_get(tmp_value, "s", &name);
571         G_VARIANT_UNREF(tmp_value);
572         if (!name)
573                 name = address;
574
575         _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL,
576                                                 _gap_agent_get_path(agent));
577
578 done:
579         g_variant_unref(reply);
580         g_variant_unref(reply_temp);
581         __bt_agent_release_memory();
582
583         BT_DBG("-");
584         return TRUE;
585 }
586
587 static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device,
588                                                                 guint passkey)
589 {
590         const gchar *address;
591         const gchar *name;
592         char *str_passkey;
593         GVariant *reply = NULL;
594         GVariant *reply_temp = NULL;
595         GVariant *tmp_value = NULL;
596
597         BT_DBG("+");
598
599         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
600         if (reply_temp == NULL) {
601                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
602                                              NULL);
603                 goto done;
604         }
605
606         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
607
608         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
609         g_variant_get(tmp_value, "s", &address);
610         G_VARIANT_UNREF(tmp_value);
611         if (!address) {
612                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
613                 goto done;
614         }
615
616         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
617         g_variant_get(tmp_value, "s", &name);
618         G_VARIANT_UNREF(tmp_value);
619         if (!name)
620                 name = address;
621
622         str_passkey = g_strdup_printf("%d", passkey);
623
624         _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
625                                                 str_passkey, NULL,
626                                                 _gap_agent_get_path(agent));
627
628         g_free(str_passkey);
629
630 done:
631         g_variant_unref(reply);
632         g_variant_unref(reply_temp);
633         __bt_agent_release_memory();
634
635         BT_DBG("-");
636         return TRUE;
637 }
638
639 static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
640                                                                 guint passkey)
641 {
642         const gchar *address;
643         const gchar *name;
644         char str_passkey[7];
645         GVariant *reply_temp = NULL;
646         GVariant *reply = NULL;
647         GVariant *tmp_value;
648         BT_DBG("+ passkey[%.6d]", passkey);
649
650         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
651
652         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
653
654         if (reply_temp == NULL) {
655                 BT_ERR("Device doesn't exist");
656                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
657                                              NULL);
658                 goto done;
659         }
660
661         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
662
663         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
664         g_variant_get(tmp_value, "s", &address);
665         G_VARIANT_UNREF(tmp_value);
666         if (!address) {
667                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
668                 goto done;
669         }
670
671         tmp_value = g_variant_lookup_value (reply, "Name", G_VARIANT_TYPE_STRING);
672         g_variant_get(tmp_value, "s", &name);
673         G_VARIANT_UNREF(tmp_value);
674         if (!name)
675                 name = address;
676
677 #ifdef TIZEN_WEARABLE
678         uint32_t device_class = 0x00;
679         uint32_t major_class;
680
681         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
682         g_variant_get(tmp_value, "u", &device_class);
683         G_VARIANT_UNREF(tmp_value);
684
685         major_class = (device_class & 0x1f00) >> 8;
686
687         if (major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) {
688                 BT_DBG("Audio device. Launch passkey pop-up");
689                 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
690                                 str_passkey, NULL, _gap_agent_get_path(agent));
691                 goto done;
692         }
693
694         if (__is_reset_required(address)) {
695                 BT_INFO("Launch system reset pop-up");
696                 _bt_launch_system_popup(BT_AGENT_EVENT_SYSTEM_RESET_REQUEST, name,
697                                 NULL, NULL, _gap_agent_get_path(agent));
698         } else {
699                 BT_INFO("Launch passkey pop-up");
700                 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED, name,
701                                 str_passkey, NULL, _gap_agent_get_path(agent));
702
703                 gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
704         }
705 #else
706         BT_DBG("LAUNCH SYSPOPUP");
707         _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
708                                                 str_passkey, NULL,
709                                                 _gap_agent_get_path(agent));
710 #endif
711
712 done:
713         g_variant_unref(reply);
714         g_variant_unref(reply_temp);
715         __bt_agent_release_memory();
716         BT_DBG("-");
717
718         return TRUE;
719 }
720
721 static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address)
722 {
723         BT_DBG("On Going Pairing is cancelled by remote\n");
724 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
725         syspopup_destroy_all();
726 #endif
727
728         __bt_agent_release_memory();
729
730         return TRUE;
731 }
732
733 static gboolean __a2dp_authorize_request_check(void)
734 {
735         /* Check for existing Media device to disconnect */
736         return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
737 }
738
739 static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
740                                                         const char *uuid)
741 {
742         const gchar *address;
743         const gchar *name;
744         gboolean trust;
745         gboolean paired;
746         GVariant *reply = NULL;
747         GVariant *reply_temp = NULL;
748         GVariant *tmp_value;
749 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
750         bool enabled;
751         tethering_h tethering = NULL;
752 #endif
753         int result = BLUETOOTH_ERROR_NONE;
754         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
755
756         BT_DBG("+");
757
758         /* Check if already Media connection exsist */
759         if (!strcasecmp(uuid, A2DP_UUID)) {
760                 gboolean ret = FALSE;
761
762                 ret = __a2dp_authorize_request_check();
763
764                 if (ret) {
765                         BT_ERR("Already one A2DP device connected \n");
766                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
767                                               NULL);
768                         goto done;
769                 }
770         }
771         /* Check completed */
772
773         if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
774              !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
775              !strcasecmp(uuid, HFP_HS_UUID) ||
776              !strcasecmp(uuid, HSP_HS_UUID) ||
777              !strcasecmp(uuid, A2DP_UUID) ||
778              !strcasecmp(uuid, HID_UUID) ||
779              !strcasecmp(uuid, SAP_UUID_OLD) ||
780              !strcasecmp(uuid, SAP_UUID_NEW) ||
781              !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
782                 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
783                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
784                                               NULL);
785
786                 goto done;
787         }
788
789         if (!strcasecmp(uuid, NAP_UUID) ||
790              !strcasecmp(uuid, GN_UUID) ||
791               !strcasecmp(uuid, BNEP_UUID)) {
792
793                 BT_DBG("Network connection request: %s", uuid);
794 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
795                 if (nap_connected_device_count >=
796                                         BT_PAN_MAX_CONNECTION) {
797                         BT_ERR("Max connection exceeded");
798                         goto fail;
799                 }
800                 int ret;
801                 ret = tethering_create(&tethering);
802
803                 if (ret != TETHERING_ERROR_NONE) {
804                         BT_ERR("Fail to create tethering: %d", ret);
805                         goto fail;
806                 }
807
808                 enabled = tethering_is_enabled(tethering, TETHERING_TYPE_BT);
809
810                 ret = tethering_destroy(tethering);
811
812                 if (ret != TETHERING_ERROR_NONE) {
813                         BT_ERR("Fail to create tethering: %d", ret);
814                 }
815
816                 if (enabled != true) {
817                         BT_ERR("BT tethering is not enabled");
818                         goto fail;
819                 }
820 #endif
821
822                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
823                                               NULL);
824                 goto done;
825 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
826 fail:
827                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
828                       NULL);
829
830                 goto done;
831 #endif
832         }
833
834         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
835         if (reply_temp == NULL) {
836                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
837                                              NULL);
838                 goto done;
839         }
840
841         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
842
843         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
844         g_variant_get(tmp_value, "s", &address);
845         G_VARIANT_UNREF(tmp_value);
846         if (!address) {
847                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
848                 goto done;
849         }
850
851         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
852         g_variant_get(tmp_value, "s", &name);
853         G_VARIANT_UNREF(tmp_value);
854         if (!name)
855                 name = address;
856
857         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
858         g_variant_get(tmp_value, "b", &trust);
859         G_VARIANT_UNREF(tmp_value);
860
861         tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
862         g_variant_get(tmp_value, "b", &paired);
863         G_VARIANT_UNREF(tmp_value);
864         if ((paired == FALSE) && (trust == FALSE)) {
865                 BT_ERR("No paired & No trusted device");
866                 gap_agent_reply_authorize(agent,
867                                 GAP_AGENT_REJECT, NULL);
868                 goto done;
869         }
870
871         BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
872
873         if (strcasecmp(uuid, OPP_UUID) == 0 &&
874              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
875                                         NULL) == TRUE) {
876                 _bt_send_event(BT_OPP_SERVER_EVENT,
877                                 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
878                                 g_variant_new("iss", result, address, name));
879
880                 goto done;
881         }
882
883         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
884                                         (char *)uuid) == TRUE) {
885                 bt_agent_osp_server_t *osp_serv;
886                 osp_serv = _gap_agent_get_osp_server(agent,
887                                                 BT_RFCOMM_SERVER, (char *)uuid);
888
889                 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
890                         BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
891                         g_variant_new("issssn", result, address, uuid,
892                                         name, osp_serv->path, osp_serv->fd));
893
894                 goto done;
895         }
896
897         if (!strcasecmp(uuid, OPP_UUID))
898                 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
899         else if (!strcasecmp(uuid, PBAP_UUID))
900                 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
901         else if (!strcasecmp(uuid, MAP_UUID))
902                 request_type = BT_AGENT_EVENT_MAP_REQUEST;
903
904         if (trust) {
905                 BT_INFO("Trusted device, so authorize\n");
906                 gap_agent_reply_authorize(agent,
907                                               GAP_AGENT_ACCEPT, NULL);
908         } else {
909                 _bt_launch_system_popup(request_type, name, NULL, NULL,
910                                                 _gap_agent_get_path(agent));
911         }
912
913 done:
914         g_variant_unref(reply);
915         g_variant_unref(reply_temp);
916         __bt_agent_release_memory();
917         BT_DBG("-");
918
919         return TRUE;
920 }
921
922 static gboolean __authorization_cancel_request(GapAgentPrivate *agent,
923                                                         const char *address)
924 {
925         BT_DBG("On Going Authorization is cancelled by remote\n");
926
927         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
928
929 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
930         syspopup_destroy_all();
931 #endif
932
933         __bt_agent_release_memory();
934
935         return TRUE;
936 }
937
938 void _bt_destroy_agent(void *agent)
939 {
940         if (!agent)
941                 return;
942
943         _gap_agent_reset_dbus((GapAgentPrivate *)agent);
944
945         g_free(agent);
946 }
947
948 void* _bt_create_agent(const char *path, gboolean adapter)
949 {
950         GAP_AGENT_FUNC_CB func_cb;
951         GDBusProxy *adapter_proxy;
952         GapAgentPrivate *agent;
953
954         adapter_proxy = _bt_get_adapter_proxy();
955         if (!adapter_proxy)
956                 return NULL;
957
958         func_cb.pincode_func = __pincode_request;
959         func_cb.display_func = __display_request;
960         func_cb.passkey_func = __passkey_request;
961         func_cb.confirm_func = __confirm_request;
962         func_cb.authorize_func = __authorize_request;
963         func_cb.pairing_cancel_func = __pairing_cancel_request;
964         func_cb.authorization_cancel_func = __authorization_cancel_request;
965
966         /* Allocate memory*/
967         agent = g_new0(GapAgentPrivate, 1);
968
969         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
970
971         if (adapter) {
972                 if (!_gap_agent_register(agent)) {
973                         _bt_destroy_agent(agent);
974                         agent = NULL;
975                 }
976         }
977
978         return agent;
979 }
980
981 gboolean _bt_agent_register_osp_server(const gint type,
982                 const char *uuid, char *path, int fd)
983 {
984         void *agent = _bt_get_adapter_agent();
985         if (!agent)
986                 return FALSE;
987
988         return _gap_agent_register_osp_server(agent, type, uuid, path, fd);
989
990 }
991
992 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
993 {
994         void *agent = _bt_get_adapter_agent();
995
996         if (!agent)
997                 return FALSE;
998
999         return _gap_agent_unregister_osp_server(agent, type, uuid);
1000 }
1001
1002 gboolean _bt_agent_reply_authorize(gboolean accept)
1003 {
1004         guint accept_val;
1005
1006         void *agent = _bt_get_adapter_agent();
1007         if (!agent)
1008                 return FALSE;
1009
1010         accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
1011
1012         return gap_agent_reply_authorize(agent, accept_val, NULL);
1013 }
1014
1015 gboolean _bt_agent_is_canceled(void)
1016 {
1017         void *agent = _bt_get_adapter_agent();
1018         if (!agent)
1019                 return FALSE;
1020
1021         return _gap_agent_is_canceled(agent);
1022 }
1023
1024 void _bt_agent_set_canceled(gboolean value)
1025 {
1026         void *agent = _bt_get_adapter_agent();
1027         if (!agent)
1028                 return;
1029
1030         return _gap_agent_set_canceled(agent, value);
1031 }
1032
1033 int _bt_agent_reply_cancellation(void)
1034 {
1035         void *agent = _bt_get_adapter_agent();
1036
1037         if (!agent)
1038                 return BLUETOOTH_ERROR_INTERNAL;
1039
1040         if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
1041                 BT_ERR("Fail to reply agent");
1042                 return BLUETOOTH_ERROR_INTERNAL;
1043         }
1044
1045         return BLUETOOTH_ERROR_NONE;
1046 }
1047
1048 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
1049 {
1050         switch ((dev_class & 0x1f00) >> 8) {
1051         case 0x05:
1052                 switch ((dev_class & 0xc0) >> 6) {
1053                 case 0x01:
1054                         /* input-keyboard" */
1055                         return TRUE;
1056                 }
1057                 break;
1058         }
1059
1060         return FALSE;
1061 }
1062
1063 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
1064                                                         const char *address)
1065 {
1066         char *pch;
1067         char *last;
1068
1069         pch = strtok_r(buffer, "= ,", &last);
1070
1071         if (pch == NULL)
1072                 return FALSE;
1073
1074         while ((pch = strtok_r(NULL, ",", &last))) {
1075                 if (0 == g_strcmp0(pch, address)) {
1076                         BT_DBG("Match found\n");
1077                         return TRUE;
1078                 }
1079         }
1080         return FALSE;
1081 }
1082
1083 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
1084                                                 const char *partial_name)
1085 {
1086         char *pch;
1087         char *last;
1088
1089         pch = strtok_r(buffer, "= ,", &last);
1090
1091         if (pch == NULL)
1092                 return FALSE;
1093
1094         while ((pch = strtok_r(NULL, ",", &last))) {
1095                 if (g_str_has_prefix(partial_name, pch)) {
1096                         BT_DBG("Match found\n");
1097                         return TRUE;
1098                 }
1099         }
1100         return FALSE;
1101 }
1102
1103 static gboolean __bt_agent_is_device_blacklist(const char *address,
1104                                                         const char *name)
1105 {
1106         char *buffer;
1107         char **lines;
1108         int i;
1109         FILE *fp;
1110         long size;
1111         size_t result;
1112
1113         BT_DBG("+");
1114
1115         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
1116
1117         if (fp == NULL) {
1118                 BT_ERR("Unable to open blacklist file");
1119                 return FALSE;
1120         }
1121
1122         fseek(fp, 0, SEEK_END);
1123         size = ftell(fp);
1124         if (size <= 0) {
1125                 BT_DBG("size is not a positive number");
1126                 fclose(fp);
1127                 return FALSE;
1128         }
1129
1130         rewind(fp);
1131
1132         buffer = g_malloc0(sizeof(char) * size);
1133         /* Fix : NULL_RETURNS */
1134         if (buffer == NULL) {
1135                 BT_ERR("Fail to allocate memory");
1136                 fclose(fp);
1137                 return FALSE;
1138         }
1139         result = fread((char *)buffer, 1, size, fp);
1140         fclose(fp);
1141         if (result != size) {
1142                 BT_ERR("Read Error");
1143                 g_free(buffer);
1144                 return FALSE;
1145         }
1146
1147         BT_DBG("Buffer = %s", buffer);
1148
1149         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
1150         g_free(buffer);
1151
1152         if (lines == NULL) {
1153                 BT_ERR("No lines in the file");
1154                 return FALSE;
1155         }
1156
1157         for (i = 0; lines[i] != NULL; i++) {
1158                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
1159                         if (__bt_agent_find_device_by_address_exactname(
1160                                                 lines[i], address))
1161                                 goto done;
1162                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
1163                         if (__bt_agent_find_device_by_address_exactname(
1164                                                 lines[i], name))
1165                                 goto done;
1166                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
1167                         if (__bt_agent_find_device_by_partial_name(lines[i],
1168                                                                 name))
1169                                 goto done;
1170                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
1171                         if (__bt_agent_find_device_by_address_exactname(
1172                                                 lines[i], address))
1173                                 goto done;
1174         }
1175         g_strfreev(lines);
1176         BT_DBG("-");
1177         return FALSE;
1178 done:
1179         BT_DBG("Found the device");
1180         g_strfreev(lines);
1181         return TRUE;
1182 }
1183
1184 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
1185                                 const gchar *address, const gchar *name)
1186 {
1187         gboolean is_headset = FALSE;
1188         gboolean is_mouse = FALSE;
1189         char lap_address[BT_LOWER_ADDRESS_LENGTH];
1190
1191         BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
1192
1193         if (address == NULL)
1194                 return FALSE;
1195
1196         switch ((dev_class & 0x1f00) >> 8) {
1197         case 0x04:
1198                 switch ((dev_class & 0xfc) >> 2) {
1199                 case 0x01:
1200                 case 0x02:
1201                         /* Headset */
1202                         is_headset = TRUE;
1203                         break;
1204                 case 0x06:
1205                         /* Headphone */
1206                         is_headset = TRUE;
1207                         break;
1208                 case 0x0b:      /* VCR */
1209                 case 0x0c:      /* Video Camera */
1210                 case 0x0d:      /* Camcorder */
1211                         break;
1212                 default:
1213                         /* Other audio device */
1214                         is_headset = TRUE;
1215                         break;
1216                 }
1217                 break;
1218         case 0x05:
1219                 switch (dev_class & 0xff) {
1220                 case 0x80:  /* 0x80: Pointing device(Mouse) */
1221                         is_mouse = TRUE;
1222                         break;
1223
1224                 case 0x40: /* 0x40: input device (BT keyboard) */
1225
1226                         /* Get the LAP(Lower Address part) */
1227                         g_strlcpy(lap_address, address, sizeof(lap_address));
1228
1229                         /* Need to Auto pair the blacklisted Keyboard */
1230                         if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
1231                                 BT_DBG("Device is not black listed\n");
1232                                 return FALSE;
1233                         } else {
1234                                 BT_ERR("Device is black listed\n");
1235                                 return TRUE;
1236                         }
1237                 }
1238         }
1239
1240         if ((!is_headset) && (!is_mouse))
1241                 return FALSE;
1242
1243         /* Get the LAP(Lower Address part) */
1244         g_strlcpy(lap_address, address, sizeof(lap_address));
1245
1246         BT_DBG("Device address = %s\n", address);
1247         BT_DBG("Address 3 byte = %s\n", lap_address);
1248
1249         if (__bt_agent_is_device_blacklist(lap_address, name)) {
1250                 BT_ERR("Device is black listed\n");
1251                 return FALSE;
1252         }
1253
1254         return TRUE;
1255 }
1256
1257 static int __bt_agent_generate_passkey(char *passkey, int size)
1258 {
1259         int i;
1260         ssize_t len;
1261         int random_fd;
1262         unsigned int value = 0;
1263
1264         if (passkey == NULL)
1265                 return -1;
1266
1267         if (size <= 0)
1268                 return -1;
1269
1270         random_fd = open("/dev/urandom", O_RDONLY);
1271
1272         if (random_fd < 0)
1273                 return -1;
1274
1275         for (i = 0; i < size; i++) {
1276                 len = read(random_fd, &value, sizeof(value));
1277                 if (len > 0)
1278                         passkey[i] = '0' + (value % 10);
1279         }
1280
1281         close(random_fd);
1282
1283         BT_DBG("passkey: %s", passkey);
1284
1285         return 0;
1286 }