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