48929308f4d10d8873e2d1f02a208514ad6e13ad
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-agent.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <malloc.h>
24 #include <stacktrim.h>
25 #include <vconf.h>
26 #include <tethering.h>
27
28 #include "bt-internal-types.h"
29 #include "bt-service-common.h"
30 #include "bt-service-agent.h"
31 #include "bt-service-gap-agent.h"
32 #include "bt-service-adapter.h"
33 #include "bt-service-event.h"
34 #include "bt-service-rfcomm-server.h"
35 #include "bt-service-device.h"
36 #include "bt-service-audio.h"
37
38 #if defined(LIBNOTIFY_SUPPORT)
39 #include "bt-popup.h"
40 #elif defined(LIBNOTIFICATION_SUPPORT)
41 #include "bt-service-agent-notification.h"
42 #else
43 #include <syspopup_caller.h>
44 #endif
45
46 #define BT_APP_AUTHENTICATION_TIMEOUT           35
47 #define BT_APP_AUTHORIZATION_TIMEOUT            15
48
49 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
50 #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
51 #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
52 #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
53 #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
54 #define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
55 #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb"
56 #define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb"
57 #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
58 #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
59 #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb"
60 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
61
62 #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent"
63 #define BT_AGENT_INTERFACE "org.bluez.Agent"
64 #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
65 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
66
67 #define BT_PIN_MAX_LENGTH 16
68 #define BT_PASSKEY_MAX_LENGTH 4
69
70 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
71
72 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
73                                                         const gchar *name);
74 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
75 static int __bt_agent_generate_passkey(char *passkey, int size);
76
77 static void __bt_agent_release_memory(void)
78 {
79         /* Release Malloc Memory*/
80         malloc_trim(0);
81
82         /* Release Stack Memory*/
83         stack_trim();
84 }
85
86 static int __syspopup_launch(gpointer user_data)
87 {
88         int ret;
89         bundle *b = (bundle *) user_data;
90 #if defined(LIBNOTIFY_SUPPORT)
91         ret = notify_launch(b);
92 #elif defined(LIBNOTIFICATION_SUPPORT)
93         ret = notification_launch(b);
94 #else
95         ret = syspopup_launch("bt-syspopup", b);
96 #endif
97         return ret;
98 }
99
100 static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data)
101 {
102         int ret;
103         bundle *b = (bundle *) user_data;
104
105         if (NULL == b) {
106                 BT_DBG("There is some problem with the user data..popup can not be created\n");
107                 return FALSE;
108         }
109         ret = __syspopup_launch(b);
110
111         if (0 > ret)
112                 BT_DBG("Sorry Can not launch popup\n");
113         else
114                 BT_DBG("Hurray Popup launched \n");
115
116         bundle_free(b);
117         return FALSE;
118 }
119
120 static int __launch_system_popup(bt_agent_event_type_t event_type,
121                                                         const char *device_name,
122                                                         char *passkey,
123                                                         const char *filename,
124                                                         const char *agent_path)
125 {
126         int ret;
127         bundle *b;
128         char event_str[BT_MAX_EVENT_STR_LENGTH + 1];
129
130         BT_DBG("_bt_agent_launch_system_popup +");
131
132         b = bundle_create();
133         if (!b)
134                 return -1;
135
136         bundle_add(b, "device-name", device_name);
137         bundle_add(b, "passkey", passkey);
138         bundle_add(b, "file", filename);
139         bundle_add(b, "agent-path", agent_path);
140
141         switch (event_type) {
142         case BT_AGENT_EVENT_PIN_REQUEST:
143                 g_strlcpy(event_str, "pin-request", sizeof(event_str));
144                 break;
145
146         case BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
147                 g_strlcpy(event_str, "passkey-confirm-request",
148                                                 sizeof(event_str));
149                 break;
150
151         case BT_AGENT_EVENT_PASSKEY_REQUEST:
152                 g_strlcpy(event_str, "passkey-request", sizeof(event_str));
153                 break;
154
155         case BT_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
156                 g_strlcpy(event_str, "passkey-display-request",
157                                                 sizeof(event_str));
158                 break;
159
160         case BT_AGENT_EVENT_AUTHORIZE_REQUEST:
161                 g_strlcpy(event_str, "authorize-request",
162                                                 sizeof(event_str));
163                 break;
164
165         case BT_AGENT_EVENT_CONFIRM_MODE_REQUEST:
166                 g_strlcpy(event_str, "confirm-mode-request",
167                                                 sizeof(event_str));
168                 break;
169
170         case BT_AGENT_EVENT_FILE_RECEIVED:
171                 g_strlcpy(event_str, "file-received", sizeof(event_str));
172                 break;
173
174         case BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
175                 g_strlcpy(event_str, "keyboard-passkey-request",
176                                                 sizeof(event_str));
177                 break;
178
179         case BT_AGENT_EVENT_TERMINATE:
180                 g_strlcpy(event_str, "terminate", sizeof(event_str));
181                 break;
182
183         case BT_AGENT_EVENT_EXCHANGE_REQUEST:
184                 g_strlcpy(event_str, "exchange-request", sizeof(event_str));
185                 break;
186
187         case BT_AGENT_EVENT_PBAP_REQUEST:
188                 g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
189                 break;
190
191         case BT_AGENT_EVENT_MAP_REQUEST:
192                 g_strlcpy(event_str, "message-request", sizeof(event_str));
193                 break;
194
195         default:
196                 bundle_free(b);
197                 return -1;
198
199         }
200
201         bundle_add(b, "event-type", event_str);
202
203         ret = __syspopup_launch(b);
204         if (0 > ret) {
205                 BT_DBG("Popup launch failed...retry %d\n", ret);
206                 g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
207                               (GSourceFunc) __bt_agent_system_popup_timer_cb,
208                                 b);
209         } else {
210                 bundle_free(b);
211         }
212
213         BT_DBG("_bt_agent_launch_system_popup -%d", ret);
214         return 0;
215 }
216
217 static gboolean __pincode_request(GapAgent *agent, DBusGProxy *device)
218 {
219         uint32_t device_class;
220         GHashTable *hash = NULL;
221         GValue *value;
222         const gchar *address;
223         const gchar *name;
224         GError *error = NULL;
225
226         BT_DBG("+\n");
227
228         dbus_g_proxy_call(device, "GetProperties", &error,
229                                 G_TYPE_INVALID,
230                                 dbus_g_type_get_map("GHashTable",
231                                                 G_TYPE_STRING, G_TYPE_VALUE),
232                                 &hash, G_TYPE_INVALID);
233         if (error) {
234                 BT_DBG("error in GetBasicProperties [%s]\n", error->message);
235                 g_error_free(error);
236                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
237                                              NULL);
238                 goto done;
239         }
240
241         value = g_hash_table_lookup(hash, "Class");
242         device_class = value ? g_value_get_uint(value) : 0;
243
244         value = g_hash_table_lookup(hash, "Address");
245         address = value ? g_value_get_string(value) : NULL;
246         if (!address) {
247                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
248                 goto done;
249         }
250
251         value = g_hash_table_lookup(hash, "Name");
252         name = value ? g_value_get_string(value) : NULL;
253         if (!name)
254                 name = address;
255
256         if (__bt_agent_is_auto_response(device_class, address, name)) {
257                 /* Use Fixed PIN "0000" for basic pairing*/
258                 _bt_set_autopair_status_in_bonding_info(TRUE);
259                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
260                                                                         NULL);
261         } else if (__bt_agent_is_hid_keyboard(device_class)) {
262                 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
263
264                 if (__bt_agent_generate_passkey(str_passkey,
265                                         BT_PASSKEY_MAX_LENGTH) != 0) {
266                         gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
267                                                 "", NULL);
268                         goto done;
269                 }
270
271                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
272                                                         str_passkey, NULL);
273
274                 __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
275                                                 name, str_passkey, NULL,
276                                                 _gap_agent_get_path(agent));
277         } else {
278                 __launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, NULL,
279                                         NULL, _gap_agent_get_path(agent));
280         }
281
282 done:
283         g_hash_table_destroy(hash);
284         __bt_agent_release_memory();
285
286         BT_DBG("-\n");
287
288         return TRUE;
289 }
290
291 static gboolean __passkey_request(GapAgent *agent, DBusGProxy *device)
292 {
293         uint32_t device_class;
294         GHashTable *hash = NULL;
295         GValue *value;
296         const gchar *address;
297         const gchar *name;
298         GError *error = NULL;
299
300         BT_DBG("+\n");
301
302         dbus_g_proxy_call(device, "GetProperties", &error,
303                                 G_TYPE_INVALID,
304                                 dbus_g_type_get_map("GHashTable",
305                                                 G_TYPE_STRING, G_TYPE_VALUE),
306                                 &hash, G_TYPE_INVALID);
307         if (error) {
308                 BT_DBG("error in GetBasicProperties [%s]\n", error->message);
309                 g_error_free(error);
310                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
311                                              NULL);
312                 goto done;
313         }
314
315         value = g_hash_table_lookup(hash, "Class");
316         device_class = value ? g_value_get_uint(value) : 0;
317
318         value = g_hash_table_lookup(hash, "Address");
319         address = value ? g_value_get_string(value) : NULL;
320         if (!address) {
321                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
322                 goto done;
323         }
324
325         value = g_hash_table_lookup(hash, "Name");
326         name = value ? g_value_get_string(value) : NULL;
327         if (!name)
328                 name = address;
329
330         __launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL,
331                                                 _gap_agent_get_path(agent));
332
333 done:
334         __bt_agent_release_memory();
335         g_hash_table_destroy(hash);
336         BT_DBG("-\n");
337
338         return TRUE;
339 }
340
341 static gboolean __display_request(GapAgent *agent, DBusGProxy *device,
342                                                                 guint passkey)
343 {
344         GHashTable *hash = NULL;
345         GValue *value;
346         const gchar *address;
347         const gchar *name;
348         GError *error = NULL;
349         char *str_passkey;
350
351         BT_DBG("+\n");
352
353         dbus_g_proxy_call(device, "GetProperties", &error,
354                                 G_TYPE_INVALID,
355                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
356                                                                  G_TYPE_VALUE),
357                                 &hash, G_TYPE_INVALID);
358         if (error) {
359                 BT_DBG("error in GetBasicProperties [%s]\n", error->message);
360                 g_error_free(error);
361                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
362                                              NULL);
363                 goto done;
364         }
365
366         value = g_hash_table_lookup(hash, "Address");
367         address = value ? g_value_get_string(value) : NULL;
368         if (!address) {
369                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
370                 goto done;
371         }
372
373         value = g_hash_table_lookup(hash, "Name");
374         name = value ? g_value_get_string(value) : NULL;
375         if (!name)
376                 name = address;
377
378         str_passkey = g_strdup_printf("%d", passkey);
379
380         __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
381                                                 str_passkey, NULL,
382                                                 _gap_agent_get_path(agent));
383
384         g_free(str_passkey);
385
386 done:
387         __bt_agent_release_memory();
388         g_hash_table_destroy(hash);
389         BT_DBG("-\n");
390
391         return TRUE;
392 }
393
394 static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device,
395                                                                 guint passkey)
396 {
397         uint32_t device_class;
398         GHashTable *hash = NULL;
399         GValue *value;
400         const gchar *address;
401         const gchar *name;
402         GError *error = NULL;
403         char str_passkey[7];
404
405         BT_DBG("+ passkey[%.6d]\n", passkey);
406
407         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
408
409         dbus_g_proxy_call(device, "GetProperties", &error,
410                                 G_TYPE_INVALID,
411                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
412                                                                  G_TYPE_VALUE),
413                                 &hash, G_TYPE_INVALID);
414         if (error) {
415                 BT_DBG("error in GetBasicProperties [%s]\n", error->message);
416                 g_error_free(error);
417                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
418                                              NULL);
419                 goto done;
420         }
421
422         value = g_hash_table_lookup(hash, "Class");
423         device_class = value ? g_value_get_uint(value) : 0;
424
425         value = g_hash_table_lookup(hash, "Address");
426         address = value ? g_value_get_string(value) : NULL;
427         if (!address) {
428                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
429                 goto done;
430         }
431
432         value = g_hash_table_lookup(hash, "Name");
433         name = value ? g_value_get_string(value) : NULL;
434         if (!name)
435                 name = address;
436
437         __launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
438                                                 str_passkey, NULL,
439                                                 _gap_agent_get_path(agent));
440
441 done:
442         __bt_agent_release_memory();
443         g_hash_table_destroy(hash);
444
445         BT_DBG("-\n");
446
447         return TRUE;
448 }
449
450 static gboolean __pairing_cancel_request(GapAgent *agent, const char *address)
451 {
452         BT_DBG("On Going Pairing is cancelled by remote\n");
453
454         gap_agent_reply_pin_code(agent, GAP_AGENT_CANCEL, "", NULL);
455
456 #ifndef LIBNOTIFY_SUPPORT
457         syspopup_destroy_all();
458 #endif
459
460         __bt_agent_release_memory();
461
462         return TRUE;
463 }
464
465 static gboolean __a2dp_authorize_request_check(void)
466 {
467         /* Check for existing Media device to disconnect */
468         return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
469 }
470
471 static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device,
472                                                         const char *uuid)
473 {
474         GHashTable *hash = NULL;
475         GValue *value;
476         const gchar *address;
477         const gchar *name;
478         bool enabled;
479         gboolean trust;
480         gboolean paired;
481         tethering_h tethering = NULL;
482         GError *error = NULL;
483         int ret;
484         int result = BLUETOOTH_ERROR_NONE;
485         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
486
487         BT_DBG("+\n");
488
489         BT_DBG("+\n");
490
491         /* Check if already Media connection exsist */
492         if (!strcasecmp(uuid, A2DP_UUID)) {
493                 gboolean ret = FALSE;
494
495                 ret = __a2dp_authorize_request_check();
496
497                 if (ret) {
498                         BT_DBG("Already one A2DP device connected \n");
499                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
500                                               NULL);
501                         goto done;
502                 }
503         }
504         /* Check completed */
505
506         if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
507              !strcasecmp(uuid, A2DP_UUID) ||
508               !strcasecmp(uuid, HID_UUID) ||
509                !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
510                 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
511                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
512                                               NULL);
513
514                 goto done;
515         }
516
517         if (!strcasecmp(uuid, NAP_UUID) ||
518              !strcasecmp(uuid, GN_UUID) ||
519               !strcasecmp(uuid, BNEP_UUID)) {
520
521                 BT_DBG("Network connection request: %s", uuid);
522                 ret = tethering_create(&tethering);
523
524                 if (ret != TETHERING_ERROR_NONE) {
525                         BT_ERR("Fail to create tethering: %d", ret);
526                         goto fail;
527                 }
528
529                 enabled = tethering_is_enabled(tethering, TETHERING_TYPE_BT);
530
531                 ret = tethering_destroy(tethering);
532
533                 if (ret != TETHERING_ERROR_NONE) {
534                         BT_ERR("Fail to create tethering: %d", ret);
535                 }
536
537                 if (enabled != true) {
538                         BT_ERR("BT tethering is not enabled");
539                         goto fail;
540                 }
541
542                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
543                                               NULL);
544                 goto done;
545 fail:
546                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
547                       NULL);
548
549                 goto done;
550         }
551
552
553         dbus_g_proxy_call(device, "GetProperties", &error, G_TYPE_INVALID,
554                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
555                                                                  G_TYPE_VALUE),
556                                 &hash, G_TYPE_INVALID);
557         if (error) {
558                 BT_DBG("error in GetBasicProperties [%s]\n", error->message);
559                 g_error_free(error);
560                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
561                                              NULL);
562                 goto done;
563         }
564
565         value = g_hash_table_lookup(hash, "Address");
566         address = value ? g_value_get_string(value) : NULL;
567         if (!address) {
568                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
569                 goto done;
570         }
571
572         value = g_hash_table_lookup(hash, "Alias");
573         name = value ? g_value_get_string(value) : NULL;
574         if (!name)
575                 name = address;
576
577         value = g_hash_table_lookup(hash, "Trusted");
578         trust = value ? g_value_get_boolean(value) : 0;
579
580         value = g_hash_table_lookup(hash, "Paired");
581         paired = value ? g_value_get_boolean(value) : 0;
582         if ((paired == FALSE) && (trust == FALSE)) {
583                 BT_DBG("No paired & No trusted device");
584                 gap_agent_reply_authorize(agent,
585                                               GAP_AGENT_REJECT, NULL);
586                 goto done;
587         }
588
589         BT_DBG("Authorization request for device [%s] Service:[%s]\n", address,
590                                                                         uuid);
591
592         if (strcasecmp(uuid, OPP_UUID) == 0 &&
593              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
594                                         NULL) == TRUE) {
595                 _bt_send_event(BT_OPP_SERVER_EVENT,
596                         BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
597                         DBUS_TYPE_INT32, &result,
598                         DBUS_TYPE_STRING, &address,
599                         DBUS_TYPE_STRING, &name,
600                         DBUS_TYPE_INVALID);
601
602                 goto done;
603         }
604
605         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
606                                         (char *)uuid) == TRUE) {
607                 bt_rfcomm_server_info_t *server_info;
608
609                 server_info = _bt_rfcomm_get_server_info_using_uuid((char *)uuid);
610                 retv_if(server_info == NULL, TRUE);
611                 retv_if(server_info->server_type != BT_CUSTOM_SERVER, TRUE);
612
613                 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
614                         BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
615                         DBUS_TYPE_INT32, &result,
616                         DBUS_TYPE_STRING, &address,
617                         DBUS_TYPE_STRING, &uuid,
618                         DBUS_TYPE_STRING, &name,
619                         DBUS_TYPE_INT16, &server_info->control_fd,
620                         DBUS_TYPE_INVALID);
621
622                 goto done;
623         }
624
625         if (!strcasecmp(uuid, OPP_UUID))
626                 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
627         else if (!strcasecmp(uuid, PBAP_UUID))
628                 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
629         else if (!strcasecmp(uuid, MAP_UUID))
630                 request_type = BT_AGENT_EVENT_MAP_REQUEST;
631
632         if (trust) {
633                 BT_DBG("Trusted device, so authorize\n");
634                 gap_agent_reply_authorize(agent,
635                                               GAP_AGENT_ACCEPT, NULL);
636         } else {
637                 __launch_system_popup(request_type, name, NULL, NULL,
638                                                 _gap_agent_get_path(agent));
639         }
640
641 done:
642         __bt_agent_release_memory();
643         g_hash_table_destroy(hash);
644
645         BT_DBG("-\n");
646
647         return TRUE;
648 }
649
650 static gboolean __authorization_cancel_request(GapAgent *agent,
651                                                         const char *address)
652 {
653         BT_DBG("On Going Authorization is cancelled by remote\n");
654
655         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
656
657 #ifndef LIBNOTIFY_SUPPORT
658         syspopup_destroy_all();
659 #endif
660
661         __bt_agent_release_memory();
662
663         return TRUE;
664 }
665
666 void _bt_destroy_agent(void *agent)
667 {
668         if (!agent)
669                 return;
670
671         _gap_agent_reset_dbus(agent);
672
673         g_object_unref(agent);
674 }
675
676 void* _bt_create_agent(const char *path, gboolean adapter)
677 {
678         GAP_AGENT_FUNC_CB func_cb;
679         DBusGProxy *adapter_proxy;
680         GapAgent* agent;
681
682         adapter_proxy = _bt_get_adapter_proxy();
683         if (!adapter_proxy)
684                 return NULL;
685
686         func_cb.pincode_func = __pincode_request;
687         func_cb.display_func = __display_request;
688         func_cb.passkey_func = __passkey_request;
689         func_cb.confirm_func = __confirm_request;
690         func_cb.authorize_func = __authorize_request;
691         func_cb.pairing_cancel_func = __pairing_cancel_request;
692         func_cb.authorization_cancel_func = __authorization_cancel_request;
693
694         agent = _gap_agent_new();
695
696         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
697
698         if (adapter) {
699                 if (!_gap_agent_register(agent)) {
700                         _bt_destroy_agent(agent);
701                         return NULL;
702                 }
703         }
704
705         return agent;
706 }
707
708 gboolean _bt_agent_register_osp_server(const gint type, const char *uuid)
709 {
710         void *agent = _bt_get_adapter_agent();
711         if (!agent)
712                 return FALSE;
713
714         return _gap_agent_register_osp_server(agent, type, uuid);
715
716 }
717
718 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
719 {
720         void *agent = _bt_get_adapter_agent();
721         if (!agent)
722                 return FALSE;
723
724         return _gap_agent_unregister_osp_server(agent, type, uuid);
725 }
726
727 gboolean _bt_agent_reply_authorize(gboolean accept)
728 {
729         guint accept_val;
730
731         void *agent = _bt_get_adapter_agent();
732         if (!agent)
733                 return FALSE;
734
735         accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
736
737         return gap_agent_reply_authorize(agent, accept_val, NULL);
738 }
739
740 gboolean _bt_agent_is_canceled(void *agent)
741 {
742         return _gap_agent_is_canceled(agent);
743 }
744
745 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
746 {
747         switch ((dev_class & 0x1f00) >> 8) {
748         case 0x05:
749                 switch ((dev_class & 0xc0) >> 6) {
750                 case 0x01:
751                         /* input-keyboard" */
752                         return TRUE;
753                 }
754                 break;
755         }
756
757         return FALSE;
758 }
759
760 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
761                                                         const char *address)
762 {
763         char *pch;
764         char *last;
765
766         pch = strtok_r(buffer, "= ,", &last);
767
768         if (pch == NULL)
769                 return FALSE;
770
771         while ((pch = strtok_r(NULL, ",", &last))) {
772                 if (0 == g_strcmp0(pch, address)) {
773                         BT_DBG("Match found\n");
774                         return TRUE;
775                 }
776         }
777         return FALSE;
778 }
779
780 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
781                                                 const char *partial_name)
782 {
783         char *pch;
784         char *last;
785
786         pch = strtok_r(buffer, "= ,", &last);
787
788         if (pch == NULL)
789                 return FALSE;
790
791         while ((pch = strtok_r(NULL, ",", &last))) {
792                 if (g_str_has_prefix(partial_name, pch)) {
793                         BT_DBG("Match found\n");
794                         return TRUE;
795                 }
796         }
797         return FALSE;
798 }
799
800 static gboolean __bt_agent_is_device_blacklist(const char *address,
801                                                         const char *name)
802 {
803         char *buffer;
804         char **lines;
805         int i;
806         FILE *fp;
807         long size;
808         size_t result;
809
810         BT_DBG("+ \n");
811
812         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
813
814         if (fp == NULL) {
815                 BT_DBG("fopen failed \n");
816                 return FALSE;
817         }
818
819         fseek(fp, 0, SEEK_END);
820         size = ftell(fp);
821         if (size <= 0) {
822                 BT_DBG("size is not a positive number");
823                 fclose(fp);
824                 return FALSE;
825         }
826
827         rewind(fp);
828
829         buffer = g_malloc0(sizeof(char) * size);
830         result = fread((char *)buffer, 1, size, fp);
831         fclose(fp);
832         if (result != size) {
833                 BT_DBG("Read Error\n");
834                 g_free(buffer);
835                 return FALSE;
836         }
837
838         BT_DBG("Buffer = %s\n", buffer);
839
840         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
841         g_free(buffer);
842
843         if (lines == NULL) {
844                 BT_DBG("No lines in the file \n");
845                 return FALSE;
846         }
847
848         for (i = 0; lines[i] != NULL; i++) {
849                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
850                         if (__bt_agent_find_device_by_address_exactname(
851                                                 lines[i], address))
852                                 goto done;
853                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
854                         if (__bt_agent_find_device_by_address_exactname(
855                                                 lines[i], name))
856                                 goto done;
857                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
858                         if (__bt_agent_find_device_by_partial_name(lines[i],
859                                                                 name))
860                                 goto done;
861         }
862         g_strfreev(lines);
863         BT_DBG("- \n");
864         return FALSE;
865 done:
866         BT_DBG("Found the device\n");
867         g_strfreev(lines);
868         return TRUE;
869 }
870
871 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
872                                 const gchar *address, const gchar *name)
873 {
874         gboolean is_headset = FALSE;
875         char lap_address[BT_LOWER_ADDRESS_LENGTH];
876
877         BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
878
879         if (address == NULL)
880                 return FALSE;
881
882         switch ((dev_class & 0x1f00) >> 8) {
883         case 0x04:
884                 switch ((dev_class & 0xfc) >> 2) {
885                 case 0x01:
886                 case 0x02:
887                         /* Headset */
888                         is_headset = TRUE;
889                         break;
890                 case 0x06:
891                         /* Headphone */
892                         is_headset = TRUE;
893                         break;
894                 case 0x0b:      /* VCR */
895                 case 0x0c:      /* Video Camera */
896                 case 0x0d:      /* Camcorder */
897                         break;
898                 default:
899                         /* Other audio device */
900                         is_headset = TRUE;
901                         break;
902                 }
903                 break;
904         }
905
906         if (!is_headset)
907                 return FALSE;
908
909         /* Get the LAP(Lower Address part) */
910         g_strlcpy(lap_address, address, sizeof(lap_address));
911
912         BT_DBG("Device address = %s\n", address);
913         BT_DBG("Address 3 byte = %s\n", lap_address);
914
915         if (__bt_agent_is_device_blacklist(lap_address, name)) {
916                 BT_DBG("Device is black listed\n");
917                 return FALSE;
918         }
919
920         return TRUE;
921 }
922
923 static int __bt_agent_generate_passkey(char *passkey, int size)
924 {
925         int i;
926         ssize_t len;
927         int random_fd;
928         unsigned int value = 0;
929
930         if (passkey == NULL)
931                 return -1;
932
933         if (size <= 0)
934                 return -1;
935
936         random_fd = open("/dev/urandom", O_RDONLY);
937
938         if (random_fd < 0)
939                 return -1;
940
941         for (i = 0; i < size; i++) {
942                 len = read(random_fd, &value, sizeof(value));
943                 passkey[i] = '0' + (value % 10);
944         }
945
946         close(random_fd);
947
948         BT_DBG("passkey: %s", passkey);
949
950         return 0;
951 }