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