7eef8dcb06bbfe360c8fbc081f8b547e8f3372e6
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-agent.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <malloc.h>
22 #include <stacktrim.h>
23
24 #if defined(LIBNOTIFY_SUPPORT)
25 #include "bt-popup.h"
26 #elif defined(LIBNOTIFICATION_SUPPORT)
27 #include "bt-service-agent-notification.h"
28 #else
29 #include <syspopup_caller.h>
30 #endif
31
32 #include <vconf.h>
33 #include <bundle_internal.h>
34
35 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
36 #include <tethering.h>
37 #endif
38
39 #include "bt-internal-types.h"
40 #include "bt-service-common.h"
41 #include "bt-service-agent.h"
42 #include "bt-service-gap-agent.h"
43 #include "bt-service-adapter.h"
44 #include "bt-service-event.h"
45 #include "bt-service-rfcomm-server.h"
46 #include "bt-service-device.h"
47 #include "bt-service-audio.h"
48
49 #define BT_APP_AUTHENTICATION_TIMEOUT           35
50 #define BT_APP_AUTHORIZATION_TIMEOUT            15
51
52 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
53 #define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
54 #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
55 #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
56 #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
57 #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
58 #define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
59 #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb"
60 #define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb"
61 #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
62 #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
63 #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb"
64 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
65 #define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00"
66 #define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a"
67
68 #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent"
69
70 #define BT_AGENT_INTERFACE "org.bluez.Agent1"
71
72 #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
73 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
74
75 #define BT_PIN_MAX_LENGTH 16
76 #define BT_PASSKEY_MAX_LENGTH 4
77
78 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
79 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
80 #define BT_PAN_MAX_CONNECTION 4
81 extern guint nap_connected_device_count;
82
83 #define G_VARIANT_UNREF(variant) \
84         g_variant_unref(variant); \
85         variant = NULL
86
87 static gboolean syspopup_mode = TRUE;
88
89 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
90                                                         const gchar *name);
91 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
92 static int __bt_agent_generate_passkey(char *passkey, int size);
93
94 static void __bt_agent_release_memory(void)
95 {
96         /* Release Malloc Memory*/
97         malloc_trim(0);
98
99         /* Release Stack Memory*/
100         stack_trim();
101 }
102
103 static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data)
104 {
105         int ret;
106         static int retry_count;
107         bundle *b = (bundle *)user_data;
108         retv_if(user_data == NULL, FALSE);
109
110         ++retry_count;
111 #if defined(LIBNOTIFY_SUPPORT)
112         ret = notify_launch(b);
113 #elif defined(LIBNOTIFICATION_SUPPORT)
114         ret = notification_launch(b);
115 #else
116         ret = syspopup_launch("bt-syspopup", b);
117 #endif
118         if (ret < 0) {
119                 BT_ERR("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..",
120                                                         ret, retry_count);
121                 if (retry_count >= BT_AGENT_SYSPOPUP_MAX_ATTEMPT) {
122                         BT_ERR("Sorry!! Max retry %d reached", retry_count);
123                         bundle_free(b);
124                         retry_count = 0;
125                         return FALSE;
126                 }
127         } else {
128                 BT_DBG("Hurray!! Finally Popup launched");
129                 retry_count = 0;
130                 bundle_free(b);
131         }
132
133         return (ret < 0) ? TRUE : FALSE;
134 }
135
136 #ifdef TIZEN_WEARABLE
137 static void __bt_popup_event_filter(GDBusConnection *connection,
138                 const gchar *sender_name,
139                 const gchar *object_path,
140                 const gchar *interface_name,
141                 const gchar *signal_name,
142                 GVariant *parameters,
143                 gpointer user_data)
144 {
145         BT_DBG("Sender Name[%s] Object Path[%s] Interface[%s] Signal[%s]",
146                         sender_name, object_path, interface_name, signal_name);
147
148         if (g_strcmp0(interface_name, "User.Bluetooth.syspopup") == 0 &&
149                         g_strcmp0(signal_name, "ResetResponse") == 0) {
150                 int response;
151
152                 g_variant_get(parameters, "(i)", &response);
153                 BT_DBG("response = %d", response);
154         }
155 }
156
157 int __bt_service_subscribe_popup(GDBusConnection *conn,
158                 gboolean subscribe)
159 {
160         static guint subs_interface_added_id = 0;
161
162         if (conn == NULL)
163                 return BLUETOOTH_ERROR_INVALID_PARAM;
164
165         if (subscribe) {
166                 if (subs_interface_added_id == 0) {
167                         subs_interface_added_id = g_dbus_connection_signal_subscribe(conn,
168                                         NULL, "User.Bluetooth.syspopup", "ResetResponse", NULL, NULL, 0,
169                                         __bt_popup_event_filter, NULL, NULL);
170                 }
171         } else {
172                 if (subs_interface_added_id > 0) {
173                         g_dbus_connection_signal_unsubscribe(conn,
174                                         subs_interface_added_id);
175                         subs_interface_added_id = 0;
176                 }
177         }
178         return BLUETOOTH_ERROR_NONE;
179 }
180
181 static void  __bt_register_popup_event_signal(void)
182 {
183         GDBusConnection *conn;
184
185         BT_DBG("+\n");
186
187         conn = _bt_get_system_gconn();
188         if (conn == NULL)
189                 return;
190
191         __bt_service_subscribe_popup(conn, TRUE);
192
193         BT_DBG("-\n");
194         return;
195 }
196
197 static gboolean __is_reset_required(const gchar *address)
198 {
199         GArray *device_list;
200         uint32_t no_of_device;
201         uint32_t i;
202         bluetooth_device_info_t info;
203         gboolean is_required = FALSE;
204
205         device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
206         if (device_list == NULL) {
207                 BT_ERR("g_array_new is failed");
208                 return FALSE;
209         }
210
211         if (_bt_get_bonded_devices(&device_list) != BLUETOOTH_ERROR_NONE) {
212                 BT_ERR("_bt_get_bonded_devices is failed");
213                 g_array_free(device_list, TRUE);
214                 return FALSE;
215         }
216
217         no_of_device = device_list->len / sizeof(bluetooth_device_info_t);
218         for (i = 0; i < no_of_device; i++) {
219                 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
220
221                 info = g_array_index(device_list, bluetooth_device_info_t, i);
222
223                 _bt_convert_addr_type_to_string(addr, info.device_address.addr);
224                 if (g_strcmp0(address, addr) == 0) {
225                         BT_DBG("This device is already in paired list");
226                         is_required = FALSE;
227                         break;
228                 }
229
230                 if (info.device_class.major_class != BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) {
231                         is_required = TRUE;
232                         break;
233                 }
234         }
235         g_array_free(device_list, TRUE);
236
237         return is_required;
238 }
239 #endif
240
241 int _bt_launch_system_popup(bt_agent_event_type_t event_type,
242                                                         const char *device_name,
243                                                         char *passkey,
244                                                         const char *filename,
245                                                         const char *agent_path)
246 {
247         int ret;
248         bundle *b;
249         char event_str[BT_MAX_EVENT_STR_LENGTH + 1];
250
251         b = bundle_create();
252         if (!b) {
253                 BT_ERR("Launching system popup failed");
254                 return -1;
255         }
256
257         bundle_add(b, "device-name", device_name);
258         bundle_add(b, "passkey", passkey);
259         bundle_add(b, "file", filename);
260         bundle_add(b, "agent-path", agent_path);
261
262         switch (event_type) {
263         case BT_AGENT_EVENT_PIN_REQUEST:
264                 g_strlcpy(event_str, "pin-request", sizeof(event_str));
265                 break;
266
267         case BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
268                 g_strlcpy(event_str, "passkey-confirm-request",
269                                                 sizeof(event_str));
270                 break;
271
272         case BT_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED:
273                 g_strlcpy(event_str, "passkey-auto-accepted",
274                                                 sizeof(event_str));
275                 break;
276
277         case BT_AGENT_EVENT_PASSKEY_REQUEST:
278                 g_strlcpy(event_str, "passkey-request", sizeof(event_str));
279                 break;
280
281         case BT_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
282                 g_strlcpy(event_str, "passkey-display-request",
283                                                 sizeof(event_str));
284                 break;
285
286         case BT_AGENT_EVENT_AUTHORIZE_REQUEST:
287                 g_strlcpy(event_str, "authorize-request",
288                                                 sizeof(event_str));
289                 break;
290
291         case BT_AGENT_EVENT_CONFIRM_MODE_REQUEST:
292                 g_strlcpy(event_str, "confirm-mode-request",
293                                                 sizeof(event_str));
294                 break;
295
296         case BT_AGENT_EVENT_FILE_RECEIVED:
297                 g_strlcpy(event_str, "file-received", sizeof(event_str));
298                 break;
299
300         case BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
301                 g_strlcpy(event_str, "keyboard-passkey-request",
302                                                 sizeof(event_str));
303                 break;
304
305         case BT_AGENT_EVENT_TERMINATE:
306                 g_strlcpy(event_str, "terminate", sizeof(event_str));
307                 break;
308
309         case BT_AGENT_EVENT_EXCHANGE_REQUEST:
310                 g_strlcpy(event_str, "exchange-request", sizeof(event_str));
311                 break;
312
313         case BT_AGENT_EVENT_PBAP_REQUEST:
314                 g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
315                 break;
316
317         case BT_AGENT_EVENT_MAP_REQUEST:
318                 g_strlcpy(event_str, "message-request", sizeof(event_str));
319                 break;
320
321 #ifdef TIZEN_WEARABLE
322         case BT_AGENT_EVENT_SYSTEM_RESET_REQUEST:
323                 __bt_register_popup_event_signal();
324                 g_strlcpy(event_str, "system-reset-request", sizeof(event_str));
325                 break;
326 #endif
327
328         case BT_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE:
329                 g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str));
330                 break;
331
332         default:
333                 BT_ERR("Invalid event type");
334                 bundle_free(b);
335                 return -1;
336
337         }
338
339         bundle_add(b, "event-type", event_str);
340
341 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
342         ret = syspopup_launch("bt-syspopup", b);
343 #endif
344         if (0 > ret) {
345                 BT_ERR("Popup launch failed...retry %d", ret);
346
347                 g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
348                               (GSourceFunc)__bt_agent_system_popup_timer_cb, b);
349         } else {
350                 bundle_free(b);
351         }
352
353         BT_INFO("_bt_agent_launch_system_popup");
354         return 0;
355 }
356
357 static GVariant *__bt_service_getall(GDBusProxy *device, const char *interface)
358 {
359         GError *error = NULL;
360         GVariant *reply;
361
362         reply = g_dbus_proxy_call_sync(device,
363                         "GetAll", g_variant_new("(s)", interface),
364                         G_DBUS_CALL_FLAGS_NONE, -1,
365                         NULL, &error);
366         if (reply == NULL) {
367                 ERR("GetAll dBUS-RPC failed");
368                 if (error) {
369                         ERR("D-Bus API failure: errCode[%x], message[%s]",
370                                 error->code, error->message);
371                         g_clear_error(&error);
372                 }
373                 return NULL;
374         }
375
376         return reply;
377 }
378
379 static gboolean __pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
380 {
381         uint32_t device_class;
382         const gchar *address;
383         const gchar *name;
384         GVariant *reply = NULL;
385         GVariant *reply_temp = NULL;
386         GVariant *tmp_value;
387         GVariant *param;
388         int result = BLUETOOTH_ERROR_NONE;
389
390         BT_DBG("+");
391
392         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
393
394         if (reply_temp == NULL) {
395                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
396                                 NULL);
397                 goto done;
398         }
399
400         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
401
402         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
403         g_variant_get(tmp_value, "u", &device_class);
404         G_VARIANT_UNREF(tmp_value);
405
406         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
407         g_variant_get(tmp_value, "s", &address);
408         G_VARIANT_UNREF(tmp_value);
409         if (!address) {
410                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
411                 goto done;
412         }
413
414         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
415         g_variant_get(tmp_value, "s", &name);
416         G_VARIANT_UNREF(tmp_value);
417         if (!name)
418                 name = address;
419
420         if (_bt_is_device_creating() == TRUE &&
421                 _bt_is_bonding_device_address(address) == TRUE &&
422                 __bt_agent_is_auto_response(device_class, address, name)) {
423                 BT_DBG("0000 Auto Pair");
424                 /* Use Fixed PIN "0000" for basic pairing */
425                 _bt_set_autopair_status_in_bonding_info(TRUE);
426                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
427                                                                         NULL);
428         } else if (__bt_agent_is_hid_keyboard(device_class)) {
429                 BT_DBG("HID Keyboard");
430                 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
431
432                 if (__bt_agent_generate_passkey(str_passkey,
433                                         BT_PASSKEY_MAX_LENGTH) != 0) {
434                         gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
435                                                 "", NULL);
436                         goto done;
437                 }
438
439                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
440                                                         str_passkey, NULL);
441
442 #ifdef AUTO_ACCEPT
443                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
444                                                                                         NULL);
445 #else
446                 if (syspopup_mode) {
447                         BT_DBG("LAUNCH SYSPOPUP");
448                         _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
449                                         name, str_passkey, NULL,
450                                         _gap_agent_get_path(agent));
451                 } else {
452                         BT_DBG("Send BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY");
453                         param = g_variant_new("(isss)", result, address, name, str_passkey);
454                         _bt_send_event(BT_ADAPTER_EVENT,
455                                         BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
456                 }
457 #endif
458         } else {
459                 BT_DBG("Show Pin entry");
460
461                 if (syspopup_mode) {
462                         BT_DBG("LAUNCH SYSPOPUP");
463                         _bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, NULL,
464                                         NULL, _gap_agent_get_path(agent));
465                 } else {
466                         BT_DBG("Send BLUETOOTH_EVENT_PIN_REQUEST");
467                         param = g_variant_new("(iss)", result, address, name);
468                         _bt_send_event(BT_ADAPTER_EVENT,
469                                         BLUETOOTH_EVENT_PIN_REQUEST, param);
470                 }
471         }
472
473 done:
474         g_variant_unref(reply);
475         g_variant_unref(reply_temp);
476         __bt_agent_release_memory();
477         BT_DBG("-");
478
479         return TRUE;
480 }
481
482 static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
483 {
484         const gchar *address;
485         const gchar *name;
486         GVariant *reply = NULL;
487         GVariant *reply_temp = NULL;
488         GVariant *tmp_value;
489         BT_DBG("+");
490
491         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
492
493         if (reply_temp == NULL) {
494                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
495                                              NULL);
496                 goto done;
497         }
498
499         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
500
501         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
502         g_variant_get(tmp_value, "s", &address);
503         G_VARIANT_UNREF(tmp_value);
504         if (!address) {
505                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
506                 goto done;
507         }
508
509         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
510         g_variant_get(tmp_value, "s", &name);
511         G_VARIANT_UNREF(tmp_value);
512         if (!name)
513                 name = address;
514
515 #ifdef AUTO_ACCEPT
516         gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
517                                                                                 NULL);
518 #else
519         if (syspopup_mode) {
520                 BT_DBG("LAUNCH SYSPOPUP");
521                 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL,
522                                         _gap_agent_get_path(agent));
523         } else {
524                 int result = BLUETOOTH_ERROR_NONE;
525                 GVariant *param;
526
527                 BT_DBG("Send BLUETOOTH_EVENT_PASSKEY_REQUEST");
528                 param = g_variant_new("(iss)", result, address, name);
529                 _bt_send_event(BT_ADAPTER_EVENT,
530                                 BLUETOOTH_EVENT_PASSKEY_REQUEST, param);
531         }
532 #endif
533
534 done:
535         g_variant_unref(reply);
536         g_variant_unref(reply_temp);
537         __bt_agent_release_memory();
538
539         BT_DBG("-");
540         return TRUE;
541 }
542
543 static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device,
544                                                                 guint passkey)
545 {
546         const gchar *address;
547         const gchar *name;
548         char *str_passkey;
549         GVariant *reply = NULL;
550         GVariant *reply_temp = NULL;
551         GVariant *tmp_value = NULL;
552
553         BT_DBG("+");
554
555         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
556         if (reply_temp == NULL) {
557                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
558                                              NULL);
559                 goto done;
560         }
561
562         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
563
564         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
565         g_variant_get(tmp_value, "s", &address);
566         G_VARIANT_UNREF(tmp_value);
567         if (!address) {
568                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
569                 goto done;
570         }
571
572         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
573         g_variant_get(tmp_value, "s", &name);
574         G_VARIANT_UNREF(tmp_value);
575         if (!name)
576                 name = address;
577
578         str_passkey = g_strdup_printf("%d", passkey);
579
580 #ifdef AUTO_ACCEPT
581         gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, str_passkey,
582                                                                                 NULL);
583 #else
584         if (syspopup_mode) {
585                 BT_DBG("LAUNCH SYSPOPUP");
586                 _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
587                                 str_passkey, NULL,
588                                 _gap_agent_get_path(agent));
589         } else {
590                 int result = BLUETOOTH_ERROR_NONE;
591                 GVariant *param;
592
593                 BT_DBG("Send BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY");
594                 param = g_variant_new("(isss)", result, address, name, str_passkey);
595                 _bt_send_event(BT_ADAPTER_EVENT,
596                                 BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
597         }
598
599 #endif
600         g_free(str_passkey);
601
602 done:
603         g_variant_unref(reply);
604         g_variant_unref(reply_temp);
605         __bt_agent_release_memory();
606
607         BT_DBG("-");
608         return TRUE;
609 }
610
611 static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
612                                                                 guint passkey)
613 {
614         const gchar *address;
615         const gchar *name;
616         char str_passkey[7];
617         GVariant *reply_temp = NULL;
618         GVariant *reply = NULL;
619         GVariant *tmp_value;
620         BT_DBG("+ passkey[%.6d]", passkey);
621
622         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
623
624         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
625
626         if (reply_temp == NULL) {
627                 BT_ERR("Device doesn't exist");
628                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
629                                              NULL);
630                 goto done;
631         }
632
633         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
634
635         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
636         g_variant_get(tmp_value, "s", &address);
637         G_VARIANT_UNREF(tmp_value);
638         if (!address) {
639                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
640                 goto done;
641         }
642
643         tmp_value = g_variant_lookup_value (reply, "Name", G_VARIANT_TYPE_STRING);
644         g_variant_get(tmp_value, "s", &name);
645         G_VARIANT_UNREF(tmp_value);
646         if (!name)
647                 name = address;
648
649 #ifdef TIZEN_WEARABLE
650         uint32_t device_class = 0x00;
651         uint32_t major_class;
652
653         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
654         g_variant_get(tmp_value, "u", &device_class);
655         G_VARIANT_UNREF(tmp_value);
656
657         major_class = (device_class & 0x1f00) >> 8;
658
659         if (major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) {
660                 BT_DBG("Audio device. Launch passkey pop-up");
661                 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
662                                 str_passkey, NULL, _gap_agent_get_path(agent));
663                 goto done;
664         }
665
666         if (__is_reset_required(address)) {
667                 BT_INFO("Launch system reset pop-up");
668                 _bt_launch_system_popup(BT_AGENT_EVENT_SYSTEM_RESET_REQUEST, name,
669                                 NULL, NULL, _gap_agent_get_path(agent));
670         } else {
671                 BT_INFO("Launch passkey pop-up");
672                 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED, name,
673                                 str_passkey, NULL, _gap_agent_get_path(agent));
674
675                 gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
676         }
677 #else
678 #ifdef AUTO_ACCEPT
679         BT_DBG("Confirm reply");
680         gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
681 #else
682         if (syspopup_mode) {
683                 BT_DBG("LAUNCH SYSPOPUP");
684                 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
685                                 str_passkey, NULL,
686                                 _gap_agent_get_path(agent));
687         } else {
688                 int result = BLUETOOTH_ERROR_NONE;
689                 GVariant *param;
690
691                 BT_DBG("Send BLUETOOTH_EVENT_PASSKEY_CONFIRM_REQUEST");
692                 param = g_variant_new("(isss)", result, address, name, str_passkey);
693                 _bt_send_event(BT_ADAPTER_EVENT,
694                                 BLUETOOTH_EVENT_PASSKEY_CONFIRM_REQUEST, param);
695         }
696 #endif
697 #endif
698
699 done:
700         g_variant_unref(reply);
701         g_variant_unref(reply_temp);
702         __bt_agent_release_memory();
703         BT_DBG("-");
704
705         return TRUE;
706 }
707
708 static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address)
709 {
710         BT_DBG("On Going Pairing is cancelled by remote\n");
711
712 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
713         syspopup_destroy_all();
714 #endif
715
716         __bt_agent_release_memory();
717
718         return TRUE;
719 }
720
721 static gboolean __a2dp_authorize_request_check(void)
722 {
723         /* Check for existing Media device to disconnect */
724         return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
725 }
726
727 static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
728                                                         const char *uuid)
729 {
730         const gchar *address;
731         const gchar *name;
732         gboolean trust;
733         gboolean paired;
734         GVariant *reply = NULL;
735         GVariant *reply_temp = NULL;
736         GVariant *tmp_value;
737 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
738         bool enabled;
739         tethering_h tethering = NULL;
740 #endif
741         int result = BLUETOOTH_ERROR_NONE;
742         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
743
744         BT_DBG("+");
745
746 #ifdef AUTO_ACCEPT
747         gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
748                                           NULL);
749         goto done;
750 #endif
751
752         /* Check if already Media connection exsist */
753         if (!strcasecmp(uuid, A2DP_UUID)) {
754                 gboolean ret = FALSE;
755
756                 ret = __a2dp_authorize_request_check();
757
758                 if (ret) {
759                         BT_ERR("Already one A2DP device connected \n");
760                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
761                                               NULL);
762                         goto done;
763                 }
764         }
765         /* Check completed */
766
767         if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
768              !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
769              !strcasecmp(uuid, HFP_HS_UUID) ||
770              !strcasecmp(uuid, HSP_HS_UUID) ||
771              !strcasecmp(uuid, A2DP_UUID) ||
772              !strcasecmp(uuid, HID_UUID) ||
773              !strcasecmp(uuid, SAP_UUID_OLD) ||
774              !strcasecmp(uuid, SAP_UUID_NEW) ||
775              !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
776                 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
777                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
778                                               NULL);
779
780                 goto done;
781         }
782
783         if (!strcasecmp(uuid, NAP_UUID) ||
784              !strcasecmp(uuid, GN_UUID) ||
785               !strcasecmp(uuid, BNEP_UUID)) {
786
787                 BT_DBG("Network connection request: %s", uuid);
788 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
789                 if (nap_connected_device_count >=
790                                         BT_PAN_MAX_CONNECTION) {
791                         BT_ERR("Max connection exceeded");
792                         goto fail;
793                 }
794                 int ret;
795                 ret = tethering_create(&tethering);
796
797                 if (ret != TETHERING_ERROR_NONE) {
798                         BT_ERR("Fail to create tethering: %d", ret);
799                         goto fail;
800                 }
801
802                 enabled = tethering_is_enabled(tethering, TETHERING_TYPE_BT);
803
804                 ret = tethering_destroy(tethering);
805
806                 if (ret != TETHERING_ERROR_NONE) {
807                         BT_ERR("Fail to create tethering: %d", ret);
808                 }
809
810                 if (enabled != true) {
811                         BT_ERR("BT tethering is not enabled");
812                         goto fail;
813                 }
814 #endif
815
816                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
817                                               NULL);
818                 goto done;
819 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
820 fail:
821                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
822                       NULL);
823
824                 goto done;
825 #endif
826         }
827
828         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
829         if (reply_temp == NULL) {
830                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
831                                              NULL);
832                 goto done;
833         }
834
835         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
836
837         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
838         g_variant_get(tmp_value, "s", &address);
839         G_VARIANT_UNREF(tmp_value);
840         if (!address) {
841                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
842                 goto done;
843         }
844
845         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
846         g_variant_get(tmp_value, "s", &name);
847         G_VARIANT_UNREF(tmp_value);
848         if (!name)
849                 name = address;
850
851         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
852         g_variant_get(tmp_value, "b", &trust);
853         G_VARIANT_UNREF(tmp_value);
854
855         tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
856         g_variant_get(tmp_value, "b", &paired);
857         G_VARIANT_UNREF(tmp_value);
858         if ((paired == FALSE) && (trust == FALSE)) {
859                 BT_ERR("No paired & No trusted device");
860                 gap_agent_reply_authorize(agent,
861                                 GAP_AGENT_REJECT, NULL);
862                 goto done;
863         }
864
865         BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
866
867         if (strcasecmp(uuid, OPP_UUID) == 0 &&
868              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
869                                         NULL) == TRUE) {
870                 _bt_send_event(BT_OPP_SERVER_EVENT,
871                                 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
872                                 g_variant_new("(iss)", result, address, name));
873
874                 goto done;
875         }
876
877         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
878                                         (char *)uuid) == TRUE) {
879                 bt_agent_osp_server_t *osp_serv;
880                 osp_serv = _gap_agent_get_osp_server(agent,
881                                                 BT_RFCOMM_SERVER, (char *)uuid);
882
883                 if (osp_serv) {
884                         _bt_send_event(BT_RFCOMM_SERVER_EVENT,
885                                 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
886                                 g_variant_new("(issssn)", result, address, uuid,
887                                                 name, osp_serv->path, osp_serv->fd));
888                 }
889
890                 goto done;
891         }
892
893         if (!strcasecmp(uuid, OPP_UUID))
894                 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
895         else if (!strcasecmp(uuid, PBAP_UUID))
896                 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
897         else if (!strcasecmp(uuid, MAP_UUID))
898                 request_type = BT_AGENT_EVENT_MAP_REQUEST;
899
900         if (trust) {
901                 BT_INFO("Trusted device, so authorize\n");
902                 gap_agent_reply_authorize(agent,
903                                               GAP_AGENT_ACCEPT, NULL);
904         } else {
905 #ifdef AUTO_ACCEPT
906                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
907 #else
908                 _bt_launch_system_popup(request_type, name, NULL, NULL,
909                                                 _gap_agent_get_path(agent));
910 #endif
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 }