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