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