Fix the waring issue
[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 #ifndef AUTO_ACCEPT
743         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
744 #endif
745
746         BT_DBG("+");
747
748 #ifdef AUTO_ACCEPT
749         gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
750                                           NULL);
751         goto done;
752 #endif
753
754         /* Check if already Media connection exsist */
755         if (!strcasecmp(uuid, A2DP_UUID)) {
756                 gboolean ret = FALSE;
757
758                 ret = __a2dp_authorize_request_check();
759
760                 if (ret) {
761                         BT_ERR("Already one A2DP device connected \n");
762                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
763                                               NULL);
764                         goto done;
765                 }
766         }
767         /* Check completed */
768
769         if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
770              !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
771              !strcasecmp(uuid, HFP_HS_UUID) ||
772              !strcasecmp(uuid, HSP_HS_UUID) ||
773              !strcasecmp(uuid, A2DP_UUID) ||
774              !strcasecmp(uuid, HID_UUID) ||
775              !strcasecmp(uuid, SAP_UUID_OLD) ||
776              !strcasecmp(uuid, SAP_UUID_NEW) ||
777              !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
778                 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
779                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
780                                               NULL);
781
782                 goto done;
783         }
784
785         if (!strcasecmp(uuid, NAP_UUID) ||
786              !strcasecmp(uuid, GN_UUID) ||
787               !strcasecmp(uuid, BNEP_UUID)) {
788
789                 BT_DBG("Network connection request: %s", uuid);
790 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
791                 if (nap_connected_device_count >=
792                                         BT_PAN_MAX_CONNECTION) {
793                         BT_ERR("Max connection exceeded");
794                         goto fail;
795                 }
796                 int ret;
797                 ret = tethering_create(&tethering);
798
799                 if (ret != TETHERING_ERROR_NONE) {
800                         BT_ERR("Fail to create tethering: %d", ret);
801                         goto fail;
802                 }
803
804                 enabled = tethering_is_enabled(tethering, TETHERING_TYPE_BT);
805
806                 ret = tethering_destroy(tethering);
807
808                 if (ret != TETHERING_ERROR_NONE) {
809                         BT_ERR("Fail to create tethering: %d", ret);
810                 }
811
812                 if (enabled != true) {
813                         BT_ERR("BT tethering is not enabled");
814                         goto fail;
815                 }
816 #endif
817
818                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
819                                               NULL);
820                 goto done;
821 #ifdef TIZEN_NETWORK_TETHERING_ENABLE
822 fail:
823                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
824                       NULL);
825
826                 goto done;
827 #endif
828         }
829
830         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
831         if (reply_temp == NULL) {
832                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
833                                              NULL);
834                 goto done;
835         }
836
837         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
838
839         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
840         g_variant_get(tmp_value, "s", &address);
841         G_VARIANT_UNREF(tmp_value);
842         if (!address) {
843                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
844                 goto done;
845         }
846
847         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
848         g_variant_get(tmp_value, "s", &name);
849         G_VARIANT_UNREF(tmp_value);
850         if (!name)
851                 name = address;
852
853         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
854         g_variant_get(tmp_value, "b", &trust);
855         G_VARIANT_UNREF(tmp_value);
856
857         tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
858         g_variant_get(tmp_value, "b", &paired);
859         G_VARIANT_UNREF(tmp_value);
860         if ((paired == FALSE) && (trust == FALSE)) {
861                 BT_ERR("No paired & No trusted device");
862                 gap_agent_reply_authorize(agent,
863                                 GAP_AGENT_REJECT, NULL);
864                 goto done;
865         }
866
867         BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
868
869         if (strcasecmp(uuid, OPP_UUID) == 0 &&
870              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
871                                         NULL) == TRUE) {
872                 _bt_send_event(BT_OPP_SERVER_EVENT,
873                                 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
874                                 g_variant_new("(iss)", result, address, name));
875
876                 goto done;
877         }
878
879         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
880                                         (char *)uuid) == TRUE) {
881                 bt_agent_osp_server_t *osp_serv;
882                 osp_serv = _gap_agent_get_osp_server(agent,
883                                                 BT_RFCOMM_SERVER, (char *)uuid);
884
885                 if (osp_serv) {
886                         _bt_send_event(BT_RFCOMM_SERVER_EVENT,
887                                 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
888                                 g_variant_new("(issssn)", result, address, uuid,
889                                                 name, osp_serv->path, osp_serv->fd));
890                 }
891
892                 goto done;
893         }
894
895         if (trust) {
896                 BT_INFO("Trusted device, so authorize\n");
897                 gap_agent_reply_authorize(agent,
898                                 GAP_AGENT_ACCEPT, NULL);
899         } else {
900 #ifdef AUTO_ACCEPT
901                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
902 #else
903                 if (!strcasecmp(uuid, OPP_UUID))
904                         request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
905                 else if (!strcasecmp(uuid, PBAP_UUID))
906                         request_type = BT_AGENT_EVENT_PBAP_REQUEST;
907                 else if (!strcasecmp(uuid, MAP_UUID))
908                         request_type = BT_AGENT_EVENT_MAP_REQUEST;
909
910                 _bt_launch_system_popup(request_type, name, NULL, NULL,
911                                 _gap_agent_get_path(agent));
912 #endif
913         }
914
915 done:
916         g_variant_unref(reply);
917         g_variant_unref(reply_temp);
918         __bt_agent_release_memory();
919         BT_DBG("-");
920
921         return TRUE;
922 }
923
924 static gboolean __authorization_cancel_request(GapAgentPrivate *agent,
925                                                         const char *address)
926 {
927         BT_DBG("On Going Authorization is cancelled by remote\n");
928
929         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
930
931 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
932         syspopup_destroy_all();
933 #endif
934
935         __bt_agent_release_memory();
936
937         return TRUE;
938 }
939
940 void _bt_destroy_agent(void *agent)
941 {
942         if (!agent)
943                 return;
944
945         _gap_agent_reset_dbus((GapAgentPrivate *)agent);
946
947         g_free(agent);
948 }
949
950 void* _bt_create_agent(const char *path, gboolean adapter)
951 {
952         GAP_AGENT_FUNC_CB func_cb;
953         GDBusProxy *adapter_proxy;
954         GapAgentPrivate *agent;
955
956         adapter_proxy = _bt_get_adapter_proxy();
957         if (!adapter_proxy)
958                 return NULL;
959
960         func_cb.pincode_func = __pincode_request;
961         func_cb.display_func = __display_request;
962         func_cb.passkey_func = __passkey_request;
963         func_cb.confirm_func = __confirm_request;
964         func_cb.authorize_func = __authorize_request;
965         func_cb.pairing_cancel_func = __pairing_cancel_request;
966         func_cb.authorization_cancel_func = __authorization_cancel_request;
967
968         /* Allocate memory*/
969         agent = g_new0(GapAgentPrivate, 1);
970
971         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
972
973         if (adapter) {
974                 if (!_gap_agent_register(agent)) {
975                         _bt_destroy_agent(agent);
976                         agent = NULL;
977                 }
978         }
979
980         return agent;
981 }
982
983 gboolean _bt_agent_register_osp_server(const gint type,
984                 const char *uuid, char *path, int fd)
985 {
986         void *agent = _bt_get_adapter_agent();
987         if (!agent)
988                 return FALSE;
989
990         return _gap_agent_register_osp_server(agent, type, uuid, path, fd);
991
992 }
993
994 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
995 {
996         void *agent = _bt_get_adapter_agent();
997
998         if (!agent)
999                 return FALSE;
1000
1001         return _gap_agent_unregister_osp_server(agent, type, uuid);
1002 }
1003
1004 gboolean _bt_agent_reply_authorize(gboolean accept)
1005 {
1006         guint accept_val;
1007
1008         void *agent = _bt_get_adapter_agent();
1009         if (!agent)
1010                 return FALSE;
1011
1012         accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
1013
1014         return gap_agent_reply_authorize(agent, accept_val, NULL);
1015 }
1016
1017 gboolean _bt_agent_is_canceled(void)
1018 {
1019         void *agent = _bt_get_adapter_agent();
1020         if (!agent)
1021                 return FALSE;
1022
1023         return _gap_agent_is_canceled(agent);
1024 }
1025
1026 void _bt_agent_set_canceled(gboolean value)
1027 {
1028         void *agent = _bt_get_adapter_agent();
1029         if (!agent)
1030                 return;
1031
1032         return _gap_agent_set_canceled(agent, value);
1033 }
1034
1035 int _bt_agent_reply_cancellation(void)
1036 {
1037         void *agent = _bt_get_adapter_agent();
1038
1039         if (!agent)
1040                 return BLUETOOTH_ERROR_INTERNAL;
1041
1042         if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
1043                 BT_ERR("Fail to reply agent");
1044                 return BLUETOOTH_ERROR_INTERNAL;
1045         }
1046
1047         return BLUETOOTH_ERROR_NONE;
1048 }
1049
1050 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
1051 {
1052         switch ((dev_class & 0x1f00) >> 8) {
1053         case 0x05:
1054                 switch ((dev_class & 0xc0) >> 6) {
1055                 case 0x01:
1056                         /* input-keyboard" */
1057                         return TRUE;
1058                 }
1059                 break;
1060         }
1061
1062         return FALSE;
1063 }
1064
1065 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
1066                                                         const char *address)
1067 {
1068         char *pch;
1069         char *last;
1070
1071         pch = strtok_r(buffer, "= ,", &last);
1072
1073         if (pch == NULL)
1074                 return FALSE;
1075
1076         while ((pch = strtok_r(NULL, ",", &last))) {
1077                 if (0 == g_strcmp0(pch, address)) {
1078                         BT_DBG("Match found\n");
1079                         return TRUE;
1080                 }
1081         }
1082         return FALSE;
1083 }
1084
1085 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
1086                                                 const char *partial_name)
1087 {
1088         char *pch;
1089         char *last;
1090
1091         pch = strtok_r(buffer, "= ,", &last);
1092
1093         if (pch == NULL)
1094                 return FALSE;
1095
1096         while ((pch = strtok_r(NULL, ",", &last))) {
1097                 if (g_str_has_prefix(partial_name, pch)) {
1098                         BT_DBG("Match found\n");
1099                         return TRUE;
1100                 }
1101         }
1102         return FALSE;
1103 }
1104
1105 static gboolean __bt_agent_is_device_blacklist(const char *address,
1106                                                         const char *name)
1107 {
1108         char *buffer;
1109         char **lines;
1110         int i;
1111         FILE *fp;
1112         long size;
1113         size_t result;
1114
1115         BT_DBG("+");
1116
1117         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
1118
1119         if (fp == NULL) {
1120                 BT_ERR("Unable to open blacklist file");
1121                 return FALSE;
1122         }
1123
1124         fseek(fp, 0, SEEK_END);
1125         size = ftell(fp);
1126         if (size <= 0) {
1127                 BT_DBG("size is not a positive number");
1128                 fclose(fp);
1129                 return FALSE;
1130         }
1131
1132         rewind(fp);
1133
1134         buffer = g_malloc0(sizeof(char) * size);
1135         /* Fix : NULL_RETURNS */
1136         if (buffer == NULL) {
1137                 BT_ERR("Fail to allocate memory");
1138                 fclose(fp);
1139                 return FALSE;
1140         }
1141         result = fread((char *)buffer, 1, size, fp);
1142         fclose(fp);
1143         if (result != size) {
1144                 BT_ERR("Read Error");
1145                 g_free(buffer);
1146                 return FALSE;
1147         }
1148
1149         BT_DBG("Buffer = %s", buffer);
1150
1151         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
1152         g_free(buffer);
1153
1154         if (lines == NULL) {
1155                 BT_ERR("No lines in the file");
1156                 return FALSE;
1157         }
1158
1159         for (i = 0; lines[i] != NULL; i++) {
1160                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
1161                         if (__bt_agent_find_device_by_address_exactname(
1162                                                 lines[i], address))
1163                                 goto done;
1164                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
1165                         if (__bt_agent_find_device_by_address_exactname(
1166                                                 lines[i], name))
1167                                 goto done;
1168                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
1169                         if (__bt_agent_find_device_by_partial_name(lines[i],
1170                                                                 name))
1171                                 goto done;
1172                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
1173                         if (__bt_agent_find_device_by_address_exactname(
1174                                                 lines[i], address))
1175                                 goto done;
1176         }
1177         g_strfreev(lines);
1178         BT_DBG("-");
1179         return FALSE;
1180 done:
1181         BT_DBG("Found the device");
1182         g_strfreev(lines);
1183         return TRUE;
1184 }
1185
1186 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
1187                                 const gchar *address, const gchar *name)
1188 {
1189         gboolean is_headset = FALSE;
1190         gboolean is_mouse = FALSE;
1191         char lap_address[BT_LOWER_ADDRESS_LENGTH];
1192
1193         BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
1194
1195         if (address == NULL)
1196                 return FALSE;
1197
1198         switch ((dev_class & 0x1f00) >> 8) {
1199         case 0x04:
1200                 switch ((dev_class & 0xfc) >> 2) {
1201                 case 0x01:
1202                 case 0x02:
1203                         /* Headset */
1204                         is_headset = TRUE;
1205                         break;
1206                 case 0x06:
1207                         /* Headphone */
1208                         is_headset = TRUE;
1209                         break;
1210                 case 0x0b:      /* VCR */
1211                 case 0x0c:      /* Video Camera */
1212                 case 0x0d:      /* Camcorder */
1213                         break;
1214                 default:
1215                         /* Other audio device */
1216                         is_headset = TRUE;
1217                         break;
1218                 }
1219                 break;
1220         case 0x05:
1221                 switch (dev_class & 0xff) {
1222                 case 0x80:  /* 0x80: Pointing device(Mouse) */
1223                         is_mouse = TRUE;
1224                         break;
1225
1226                 case 0x40: /* 0x40: input device (BT keyboard) */
1227
1228                         /* Get the LAP(Lower Address part) */
1229                         g_strlcpy(lap_address, address, sizeof(lap_address));
1230
1231                         /* Need to Auto pair the blacklisted Keyboard */
1232                         if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
1233                                 BT_DBG("Device is not black listed\n");
1234                                 return FALSE;
1235                         } else {
1236                                 BT_ERR("Device is black listed\n");
1237                                 return TRUE;
1238                         }
1239                 }
1240         }
1241
1242         if ((!is_headset) && (!is_mouse))
1243                 return FALSE;
1244
1245         /* Get the LAP(Lower Address part) */
1246         g_strlcpy(lap_address, address, sizeof(lap_address));
1247
1248         BT_DBG("Device address = %s\n", address);
1249         BT_DBG("Address 3 byte = %s\n", lap_address);
1250
1251         if (__bt_agent_is_device_blacklist(lap_address, name)) {
1252                 BT_ERR("Device is black listed\n");
1253                 return FALSE;
1254         }
1255
1256         return TRUE;
1257 }
1258
1259 static int __bt_agent_generate_passkey(char *passkey, int size)
1260 {
1261         int i;
1262         ssize_t len;
1263         int random_fd;
1264         unsigned int value = 0;
1265
1266         if (passkey == NULL)
1267                 return -1;
1268
1269         if (size <= 0)
1270                 return -1;
1271
1272         random_fd = open("/dev/urandom", O_RDONLY);
1273
1274         if (random_fd < 0)
1275                 return -1;
1276
1277         for (i = 0; i < size; i++) {
1278                 len = read(random_fd, &value, sizeof(value));
1279                 if (len > 0)
1280                         passkey[i] = '0' + (value % 10);
1281         }
1282
1283         close(random_fd);
1284
1285         BT_DBG("passkey: %s", passkey);
1286
1287         return 0;
1288 }