d48af2a1195df9d7fc5c7e198f2cac4f452a1722
[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_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
64 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
65
66 #define BT_PIN_MAX_LENGTH 16
67 #define BT_PASSKEY_MAX_LENGTH 4
68
69 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
70
71 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
72                                                         const gchar *name);
73 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
74 static int __bt_agent_generate_passkey(char *passkey, int size);
75
76 static void __bt_agent_release_memory(void)
77 {
78         /* Release Malloc Memory*/
79         malloc_trim(0);
80
81         /* Release Stack Memory*/
82         stack_trim();
83 }
84
85 static int __syspopup_launch(gpointer user_data)
86 {
87         int ret;
88         bundle *b = (bundle *) user_data;
89 #if defined(LIBNOTIFY_SUPPORT)
90         ret = notify_launch(b);
91 #elif defined(LIBNOTIFICATION_SUPPORT)
92         ret = notification_launch(b);
93 #else
94         ret = syspopup_launch("bt-syspopup", b);
95 #endif
96         return ret;
97 }
98
99 static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data)
100 {
101         int ret;
102         bundle *b = (bundle *) user_data;
103
104         if (NULL == b) {
105                 BT_DBG("There is some problem with the user data..popup can not be created\n");
106                 return FALSE;
107         }
108         ret = __syspopup_launch(b);
109
110         if (0 > ret)
111                 BT_DBG("Sorry Can not launch popup\n");
112         else
113                 BT_DBG("Hurray Popup launched \n");
114
115         bundle_free(b);
116         return FALSE;
117 }
118
119 static int __launch_system_popup(bt_agent_event_type_t event_type,
120                                                         const char *device_name,
121                                                         char *passkey,
122                                                         const char *filename,
123                                                         const char *agent_path)
124 {
125         int ret;
126         bundle *b;
127         char event_str[BT_MAX_EVENT_STR_LENGTH + 1];
128
129         BT_DBG("_bt_agent_launch_system_popup +");
130
131         b = bundle_create();
132         if (!b)
133                 return -1;
134
135         bundle_add(b, "device-name", device_name);
136         bundle_add(b, "passkey", passkey);
137         bundle_add(b, "file", filename);
138         bundle_add(b, "agent-path", agent_path);
139
140         switch (event_type) {
141         case BT_AGENT_EVENT_PIN_REQUEST:
142                 g_strlcpy(event_str, "pin-request", sizeof(event_str));
143                 break;
144
145         case BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
146                 g_strlcpy(event_str, "passkey-confirm-request",
147                                                 sizeof(event_str));
148                 break;
149
150         case BT_AGENT_EVENT_PASSKEY_REQUEST:
151                 g_strlcpy(event_str, "passkey-request", sizeof(event_str));
152                 break;
153
154         case BT_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
155                 g_strlcpy(event_str, "passkey-display-request",
156                                                 sizeof(event_str));
157                 break;
158
159         case BT_AGENT_EVENT_AUTHORIZE_REQUEST:
160                 g_strlcpy(event_str, "authorize-request",
161                                                 sizeof(event_str));
162                 break;
163
164         case BT_AGENT_EVENT_CONFIRM_MODE_REQUEST:
165                 g_strlcpy(event_str, "confirm-mode-request",
166                                                 sizeof(event_str));
167                 break;
168
169         case BT_AGENT_EVENT_FILE_RECEIVED:
170                 g_strlcpy(event_str, "file-received", sizeof(event_str));
171                 break;
172
173         case BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
174                 g_strlcpy(event_str, "keyboard-passkey-request",
175                                                 sizeof(event_str));
176                 break;
177
178         case BT_AGENT_EVENT_TERMINATE:
179                 g_strlcpy(event_str, "terminate", sizeof(event_str));
180                 break;
181
182         case BT_AGENT_EVENT_EXCHANGE_REQUEST:
183                 g_strlcpy(event_str, "exchange-request", sizeof(event_str));
184                 break;
185
186         case BT_AGENT_EVENT_PBAP_REQUEST:
187                 g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
188                 break;
189
190         case BT_AGENT_EVENT_MAP_REQUEST:
191                 g_strlcpy(event_str, "message-request", sizeof(event_str));
192                 break;
193
194         default:
195                 bundle_free(b);
196                 return -1;
197
198         }
199
200         bundle_add(b, "event-type", event_str);
201
202         ret = __syspopup_launch(b);
203         if (0 > ret) {
204                 BT_DBG("Popup launch failed...retry %d\n", ret);
205                 g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
206                               (GSourceFunc) __bt_agent_system_popup_timer_cb,
207                                 b);
208         } else {
209                 bundle_free(b);
210         }
211
212         BT_DBG("_bt_agent_launch_system_popup -%d", ret);
213         return 0;
214 }
215
216 static gboolean __pincode_request(GapAgent *agent, DBusGProxy *device)
217 {
218         uint32_t device_class;
219         GHashTable *hash = NULL;
220         GValue *value;
221         const gchar *address;
222         const gchar *name;
223         GError *error = NULL;
224
225         BT_DBG("+\n");
226
227         dbus_g_proxy_call(device, "GetAll", &error,
228                                 G_TYPE_STRING, BT_DEVICE_INTERFACE,
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 GetAll [%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, "GetAll", &error,
303                                 G_TYPE_STRING, BT_DEVICE_INTERFACE,
304                                 G_TYPE_INVALID,
305                                 dbus_g_type_get_map("GHashTable",
306                                                 G_TYPE_STRING, G_TYPE_VALUE),
307                                 &hash, G_TYPE_INVALID);
308         if (error) {
309                 BT_DBG("error in GetAll [%s]\n", error->message);
310                 g_error_free(error);
311                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
312                                              NULL);
313                 goto done;
314         }
315
316         value = g_hash_table_lookup(hash, "Class");
317         device_class = value ? g_value_get_uint(value) : 0;
318
319         value = g_hash_table_lookup(hash, "Address");
320         address = value ? g_value_get_string(value) : NULL;
321         if (!address) {
322                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
323                 goto done;
324         }
325
326         value = g_hash_table_lookup(hash, "Name");
327         name = value ? g_value_get_string(value) : NULL;
328         if (!name)
329                 name = address;
330
331         __launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL,
332                                                 _gap_agent_get_path(agent));
333
334 done:
335         __bt_agent_release_memory();
336         g_hash_table_destroy(hash);
337         BT_DBG("-\n");
338
339         return TRUE;
340 }
341
342 static gboolean __display_request(GapAgent *agent, DBusGProxy *device,
343                                                                 guint passkey)
344 {
345         GHashTable *hash = NULL;
346         GValue *value;
347         const gchar *address;
348         const gchar *name;
349         GError *error = NULL;
350         char *str_passkey;
351
352         BT_DBG("+\n");
353
354         dbus_g_proxy_call(device, "GetAll", &error,
355                                 G_TYPE_STRING, BT_DEVICE_INTERFACE,
356                                 G_TYPE_INVALID,
357                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
358                                                                  G_TYPE_VALUE),
359                                 &hash, G_TYPE_INVALID);
360         if (error) {
361                 BT_DBG("error in GetAll [%s]\n", error->message);
362                 g_error_free(error);
363                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
364                                              NULL);
365                 goto done;
366         }
367
368         value = g_hash_table_lookup(hash, "Address");
369         address = value ? g_value_get_string(value) : NULL;
370         if (!address) {
371                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
372                 goto done;
373         }
374
375         value = g_hash_table_lookup(hash, "Name");
376         name = value ? g_value_get_string(value) : NULL;
377         if (!name)
378                 name = address;
379
380         str_passkey = g_strdup_printf("%d", passkey);
381
382         __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
383                                                 str_passkey, NULL,
384                                                 _gap_agent_get_path(agent));
385
386         g_free(str_passkey);
387
388 done:
389         __bt_agent_release_memory();
390         g_hash_table_destroy(hash);
391         BT_DBG("-\n");
392
393         return TRUE;
394 }
395
396 static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device,
397                                                                 guint passkey)
398 {
399         uint32_t device_class;
400         GHashTable *hash = NULL;
401         GValue *value;
402         const gchar *address;
403         const gchar *name;
404         GError *error = NULL;
405         char str_passkey[7];
406
407         BT_DBG("+ passkey[%.6d]\n", passkey);
408
409         dbus_g_proxy_call(device, "GetAll", &error,
410                                 G_TYPE_STRING, BT_DEVICE_INTERFACE,
411                                 G_TYPE_INVALID,
412                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
413                                 G_TYPE_VALUE), &hash, G_TYPE_INVALID);
414
415         if (error) {
416                 BT_DBG("error in GetAll [%s]\n", error->message);
417                 g_error_free(error);
418                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
419                                              NULL);
420                 goto done;
421         }
422
423         value = g_hash_table_lookup(hash, "Class");
424         device_class = value ? g_value_get_uint(value) : 0;
425
426         value = g_hash_table_lookup(hash, "Address");
427         address = value ? g_value_get_string(value) : NULL;
428         if (!address) {
429                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
430                 goto done;
431         }
432
433         value = g_hash_table_lookup(hash, "Name");
434         name = value ? g_value_get_string(value) : NULL;
435         if (!name)
436                 name = address;
437
438         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
439
440         __launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
441                                                 str_passkey, NULL,
442                                                 _gap_agent_get_path(agent));
443 done:
444         __bt_agent_release_memory();
445         g_hash_table_destroy(hash);
446
447         BT_DBG("-\n");
448
449         return TRUE;
450 }
451
452 static gboolean __pairing_cancel_request(GapAgent *agent, const char *address)
453 {
454         BT_DBG("On Going Pairing is cancelled by remote\n");
455
456         gap_agent_reply_pin_code(agent, GAP_AGENT_CANCEL, "", NULL);
457
458 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
459         syspopup_destroy_all();
460 #endif
461
462         __bt_agent_release_memory();
463
464         return TRUE;
465 }
466
467 static gboolean __a2dp_authorize_request_check(void)
468 {
469         /* Check for existing Media device to disconnect */
470         return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
471 }
472
473 static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device,
474                                                         const char *uuid)
475 {
476         GHashTable *hash = NULL;
477         GValue *value;
478         const gchar *address;
479         const gchar *name;
480         bool enabled;
481         gboolean trust;
482         gboolean paired;
483         tethering_h tethering = NULL;
484         GError *error = NULL;
485         int ret;
486         int result = BLUETOOTH_ERROR_NONE;
487         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
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         dbus_g_proxy_call(device, "GetAll", &error,
553                                 G_TYPE_STRING, BT_DEVICE_INTERFACE,
554                                 G_TYPE_INVALID,
555                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
556                                                                  G_TYPE_VALUE),
557                                 &hash, G_TYPE_INVALID);
558         if (error) {
559                 BT_DBG("error in GetAll [%s]\n", error->message);
560                 g_error_free(error);
561                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
562                                              NULL);
563                 goto done;
564         }
565
566         value = g_hash_table_lookup(hash, "Address");
567         address = value ? g_value_get_string(value) : NULL;
568         if (!address) {
569                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
570                 goto done;
571         }
572
573         value = g_hash_table_lookup(hash, "Alias");
574         name = value ? g_value_get_string(value) : NULL;
575         if (!name)
576                 name = address;
577
578         value = g_hash_table_lookup(hash, "Trusted");
579         trust = value ? g_value_get_boolean(value) : 0;
580
581         value = g_hash_table_lookup(hash, "Paired");
582         paired = value ? g_value_get_boolean(value) : 0;
583         if ((paired == FALSE) && (trust == FALSE)) {
584                 BT_DBG("No paired & No trusted device");
585                 gap_agent_reply_authorize(agent,
586                                               GAP_AGENT_REJECT, NULL);
587                 goto done;
588         }
589
590         BT_DBG("Authorization request for device [%s] Service:[%s]\n", address,
591                                                                         uuid);
592
593         if (strcasecmp(uuid, OPP_UUID) == 0 &&
594              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
595                                         NULL) == TRUE) {
596                 _bt_send_event(BT_OPP_SERVER_EVENT,
597                         BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
598                         DBUS_TYPE_INT32, &result,
599                         DBUS_TYPE_STRING, &address,
600                         DBUS_TYPE_STRING, &name,
601                         DBUS_TYPE_INVALID);
602
603                 goto done;
604         }
605
606         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
607                                         (char *)uuid) == TRUE) {
608                 bt_rfcomm_server_info_t *server_info;
609
610                 server_info = _bt_rfcomm_get_server_info_using_uuid((char *)uuid);
611                 retv_if(server_info == NULL, TRUE);
612                 retv_if(server_info->server_type != BT_CUSTOM_SERVER, TRUE);
613
614                 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
615                         BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
616                         DBUS_TYPE_INT32, &result,
617                         DBUS_TYPE_STRING, &address,
618                         DBUS_TYPE_STRING, &uuid,
619                         DBUS_TYPE_STRING, &name,
620                         DBUS_TYPE_INT16, &server_info->control_fd,
621                         DBUS_TYPE_INVALID);
622
623                 goto done;
624         }
625
626         if (!strcasecmp(uuid, OPP_UUID))
627                 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
628         else if (!strcasecmp(uuid, PBAP_UUID))
629                 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
630         else if (!strcasecmp(uuid, MAP_UUID))
631                 request_type = BT_AGENT_EVENT_MAP_REQUEST;
632
633         if (trust) {
634                 BT_DBG("Trusted device, so authorize\n");
635                 gap_agent_reply_authorize(agent,
636                                               GAP_AGENT_ACCEPT, NULL);
637         } else {
638                 __launch_system_popup(request_type, name, NULL, NULL,
639                                                 _gap_agent_get_path(agent));
640         }
641
642 done:
643         __bt_agent_release_memory();
644         g_hash_table_destroy(hash);
645
646         BT_DBG("-\n");
647
648         return TRUE;
649 }
650
651 static gboolean __authorization_cancel_request(GapAgent *agent,
652                                                         const char *address)
653 {
654         BT_DBG("On Going Authorization is cancelled by remote\n");
655
656         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
657
658 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
659         syspopup_destroy_all();
660 #endif
661
662         __bt_agent_release_memory();
663
664         return TRUE;
665 }
666
667 void _bt_destroy_agent(void *agent)
668 {
669         if (!agent)
670                 return;
671
672         _gap_agent_reset_dbus(agent);
673
674         g_object_unref(agent);
675 }
676
677 void* _bt_create_agent(const char *path, gboolean adapter)
678 {
679         GAP_AGENT_FUNC_CB func_cb;
680         GapAgent* agent;
681
682         func_cb.pincode_func = __pincode_request;
683         func_cb.display_func = __display_request;
684         func_cb.passkey_func = __passkey_request;
685         func_cb.confirm_func = __confirm_request;
686         func_cb.authorize_func = __authorize_request;
687         func_cb.pairing_cancel_func = __pairing_cancel_request;
688         func_cb.authorization_cancel_func = __authorization_cancel_request;
689
690         agent = _gap_agent_new();
691
692         _gap_agent_setup_dbus(agent, &func_cb, path);
693
694         if (adapter) {
695                 if (!_gap_agent_register(agent)) {
696                         _bt_destroy_agent(agent);
697                         return NULL;
698                 }
699         }
700
701         return agent;
702 }
703
704 gboolean _bt_agent_register_osp_server(const gint type, const char *uuid)
705 {
706         void *agent = _bt_get_adapter_agent();
707         if (!agent)
708                 return FALSE;
709
710         return _gap_agent_register_osp_server(agent, type, uuid);
711
712 }
713
714 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
715 {
716         void *agent = _bt_get_adapter_agent();
717         if (!agent)
718                 return FALSE;
719
720         return _gap_agent_unregister_osp_server(agent, type, uuid);
721 }
722
723 gboolean _bt_agent_reply_authorize(gboolean accept)
724 {
725         guint accept_val;
726
727         void *agent = _bt_get_adapter_agent();
728         if (!agent)
729                 return FALSE;
730
731         accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
732
733         return gap_agent_reply_authorize(agent, accept_val, NULL);
734 }
735
736 gboolean _bt_agent_is_canceled(void *agent)
737 {
738         return _gap_agent_is_canceled(agent);
739 }
740
741 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
742 {
743         switch ((dev_class & 0x1f00) >> 8) {
744         case 0x05:
745                 switch ((dev_class & 0xc0) >> 6) {
746                 case 0x01:
747                         /* input-keyboard" */
748                         return TRUE;
749                 }
750                 break;
751         }
752
753         return FALSE;
754 }
755
756 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
757                                                         const char *address)
758 {
759         char *pch;
760         char *last;
761
762         pch = strtok_r(buffer, "= ,", &last);
763
764         if (pch == NULL)
765                 return FALSE;
766
767         while ((pch = strtok_r(NULL, ",", &last))) {
768                 if (0 == g_strcmp0(pch, address)) {
769                         BT_DBG("Match found\n");
770                         return TRUE;
771                 }
772         }
773         return FALSE;
774 }
775
776 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
777                                                 const char *partial_name)
778 {
779         char *pch;
780         char *last;
781
782         pch = strtok_r(buffer, "= ,", &last);
783
784         if (pch == NULL)
785                 return FALSE;
786
787         while ((pch = strtok_r(NULL, ",", &last))) {
788                 if (g_str_has_prefix(partial_name, pch)) {
789                         BT_DBG("Match found\n");
790                         return TRUE;
791                 }
792         }
793         return FALSE;
794 }
795
796 static gboolean __bt_agent_is_device_blacklist(const char *address,
797                                                         const char *name)
798 {
799         char *buffer;
800         char **lines;
801         int i;
802         FILE *fp;
803         long size;
804         size_t result;
805
806         BT_DBG("+ \n");
807
808         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
809
810         if (fp == NULL) {
811                 BT_DBG("fopen failed \n");
812                 return FALSE;
813         }
814
815         fseek(fp, 0, SEEK_END);
816         size = ftell(fp);
817         if (size <= 0) {
818                 BT_DBG("size is not a positive number");
819                 fclose(fp);
820                 return FALSE;
821         }
822
823         rewind(fp);
824
825         buffer = g_malloc0(sizeof(char) * size);
826         result = fread((char *)buffer, 1, size, fp);
827         fclose(fp);
828         if (result != size) {
829                 BT_DBG("Read Error\n");
830                 g_free(buffer);
831                 return FALSE;
832         }
833
834         BT_DBG("Buffer = %s\n", buffer);
835
836         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
837         g_free(buffer);
838
839         if (lines == NULL) {
840                 BT_DBG("No lines in the file \n");
841                 return FALSE;
842         }
843
844         for (i = 0; lines[i] != NULL; i++) {
845                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
846                         if (__bt_agent_find_device_by_address_exactname(
847                                                 lines[i], address))
848                                 goto done;
849                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
850                         if (__bt_agent_find_device_by_address_exactname(
851                                                 lines[i], name))
852                                 goto done;
853                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
854                         if (__bt_agent_find_device_by_partial_name(lines[i],
855                                                                 name))
856                                 goto done;
857         }
858         g_strfreev(lines);
859         BT_DBG("- \n");
860         return FALSE;
861 done:
862         BT_DBG("Found the device\n");
863         g_strfreev(lines);
864         return TRUE;
865 }
866
867 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
868                                 const gchar *address, const gchar *name)
869 {
870         gboolean is_headset = FALSE;
871         char lap_address[BT_LOWER_ADDRESS_LENGTH];
872
873         BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
874
875         if (address == NULL)
876                 return FALSE;
877
878         switch ((dev_class & 0x1f00) >> 8) {
879         case 0x04:
880                 switch ((dev_class & 0xfc) >> 2) {
881                 case 0x01:
882                 case 0x02:
883                         /* Headset */
884                         is_headset = TRUE;
885                         break;
886                 case 0x06:
887                         /* Headphone */
888                         is_headset = TRUE;
889                         break;
890                 case 0x0b:      /* VCR */
891                 case 0x0c:      /* Video Camera */
892                 case 0x0d:      /* Camcorder */
893                         break;
894                 default:
895                         /* Other audio device */
896                         is_headset = TRUE;
897                         break;
898                 }
899                 break;
900         }
901
902         if (!is_headset)
903                 return FALSE;
904
905         /* Get the LAP(Lower Address part) */
906         g_strlcpy(lap_address, address, sizeof(lap_address));
907
908         BT_DBG("Device address = %s\n", address);
909         BT_DBG("Address 3 byte = %s\n", lap_address);
910
911         if (__bt_agent_is_device_blacklist(lap_address, name)) {
912                 BT_DBG("Device is black listed\n");
913                 return FALSE;
914         }
915
916         return TRUE;
917 }
918
919 static int __bt_agent_generate_passkey(char *passkey, int size)
920 {
921         int i;
922         ssize_t len;
923         int random_fd;
924         unsigned int value = 0;
925
926         if (passkey == NULL)
927                 return -1;
928
929         if (size <= 0)
930                 return -1;
931
932         random_fd = open("/dev/urandom", O_RDONLY);
933
934         if (random_fd < 0)
935                 return -1;
936
937         for (i = 0; i < size; i++) {
938                 len = read(random_fd, &value, sizeof(value));
939                 passkey[i] = '0' + (value % 10);
940         }
941
942         close(random_fd);
943
944         BT_DBG("passkey: %s", passkey);
945
946         return 0;
947 }