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