Apply tizen 3.0 based product patchsets
[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 #include <vconf.h>
24 #include <bundle_internal.h>
25
26 #include "bt-internal-types.h"
27 #include "bt-service-common.h"
28 #include "bt-service-agent.h"
29 #include "bt-service-gap-agent.h"
30 #include "bt-service-adapter.h"
31 #include "bt-service-event.h"
32 #include "bt-service-rfcomm-server.h"
33 #include "bt-service-device.h"
34 #include "bt-service-audio.h"
35
36 #ifdef TIZEN_FEATURE_BT_DPM
37 #include "bt-service-dpm.h"
38 #endif
39
40 #define BT_APP_AUTHENTICATION_TIMEOUT           35
41 #define BT_APP_AUTHORIZATION_TIMEOUT            15
42
43 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
44 #define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
45 #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
46 #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
47 #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
48 #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
49 #define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
50 #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb"
51 #define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb"
52 #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
53 #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
54 #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb"
55 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
56 #define HID_DEVICE_UUID         "00001124-0000-1000-8000-00805f9b43bf"
57 #define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00"
58 #define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a"
59 #define IOTIVITY_UUID "12341234-1C25-481F-9DFB-59193D238280"
60
61 #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent"
62
63 #define BT_AGENT_INTERFACE "org.bluez.Agent1"
64
65 #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
66 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
67
68 #define BT_PASSKEY_MAX_LENGTH 4
69
70 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
71 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
72 #define BT_PAN_MAX_CONNECTION 4
73
74 extern guint nap_connected_device_count;
75
76 static char *passkey_watcher;
77
78 #define G_VARIANT_UNREF(variant) \
79         g_variant_unref(variant); \
80         variant = NULL
81
82 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
83                                                         const gchar *name);
84 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
85 static int __bt_agent_generate_passkey(char *passkey, int size);
86
87 static void __bt_agent_release_memory(void)
88 {
89         /* Release Malloc Memory*/
90         malloc_trim(0);
91
92         /* Release Stack Memory*/
93         stack_trim();
94 }
95
96 static GVariant *__bt_service_getall(GDBusProxy *device, const char *interface)
97 {
98         GError *error = NULL;
99         GVariant *reply;
100
101         reply = g_dbus_proxy_call_sync(device,
102                         "GetAll", g_variant_new("(s)", interface),
103                         G_DBUS_CALL_FLAGS_NONE, -1,
104                         NULL, &error);
105         if (reply == NULL) {
106                 ERR("GetAll dBUS-RPC failed");
107                 if (error) {
108                         ERR("D-Bus API failure: errCode[%x], message[%s]",
109                                 error->code, error->message);
110                         g_clear_error(&error);
111                 }
112                 return NULL;
113         }
114
115         return reply;
116 }
117
118 static gboolean __pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
119 {
120         uint32_t device_class;
121         gchar *address = NULL;
122         unsigned char auth_info[5] = {0, };
123         gchar *name = NULL;
124         GVariant *reply = NULL;
125         GVariant *reply_temp = NULL;
126         GVariant *tmp_value;
127         char pin_code[BLUETOOTH_PIN_CODE_MAX_LENGTH + 1];
128         int ret = BLUETOOTH_ERROR_NONE;
129 #ifdef TIZEN_FEATURE_BT_DPM
130         int pairing_state = DPM_STATUS_ERROR;
131 #endif
132
133         BT_DBG("+");
134
135 #ifdef TIZEN_FEATURE_BT_DPM
136         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
137         if (pairing_state == DPM_RESTRICTED) {
138                 BT_ERR("Not allow to pair the device");
139                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
140                 __bt_agent_release_memory();
141                 return TRUE;
142         }
143 #endif
144
145         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
146
147         if (reply_temp == NULL) {
148                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
149                                 NULL);
150                 goto done;
151         }
152
153         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
154
155         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
156         g_variant_get(tmp_value, "u", &device_class);
157         G_VARIANT_UNREF(tmp_value);
158
159         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
160         g_variant_get(tmp_value, "s", &address);
161         G_VARIANT_UNREF(tmp_value);
162         if (!address) {
163                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
164                 goto done;
165         }
166
167         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
168         g_variant_get(tmp_value, "s", &name);
169         G_VARIANT_UNREF(tmp_value);
170         if (!name) {
171                 BT_DBG("Replacing the name with address");
172                 name = g_strdup(address);
173         } else {
174                 BT_INFO("Name = %s, Address = %s, Class = 0x%x", name, address, device_class);
175                 if (name[0] == '\0') {
176                         g_free(name);
177                         BT_DBG("Name[0]=NULL, Replacing the name with address");
178                         name = g_strdup(address);
179                 }
180         }
181
182         __bt_get_auth_info(reply, (char *)auth_info);
183         if (_bt_is_device_creating() == TRUE &&
184                 _bt_is_bonding_device_address(address) == TRUE &&
185                 __bt_agent_is_auto_response(device_class, address, name)) {
186                 BT_DBG("0000 Auto Pair");
187                 /* Use Fixed PIN "0000" for basic pairing */
188                 _bt_set_autopair_status_in_bonding_info(TRUE);
189                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
190                                                                         NULL);
191         } else if (__bt_agent_is_hid_keyboard(device_class)) {
192                 BT_DBG("HID Keyboard");
193                 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
194
195                 if (__bt_agent_generate_passkey(str_passkey,
196                                         BT_PASSKEY_MAX_LENGTH) != 0) {
197                         gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
198                                                 "", NULL);
199                         goto done;
200                 }
201
202                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
203                                                         str_passkey, NULL);
204
205                 if (headed_plugin_info->plugin_headed_enabled) {
206                         headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
207                                         name, auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
208                 } else {
209                         GVariant *param = NULL;
210                         param = g_variant_new("(isss)", ret, address, name, str_passkey);
211                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
212                 }
213         } else if (_bt_get_device_pin_code(address, pin_code)
214                                 == BLUETOOTH_ERROR_NONE) {
215                 BT_DBG("Use stored PIN code(%s)", pin_code);
216                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, pin_code,
217                                                                         NULL);
218                 goto done;
219         } else {
220                 if (headed_plugin_info->plugin_headed_enabled) {
221                         BT_DBG("Show Pin entry");
222                         headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, auth_info,
223                                         NULL, NULL, _gap_agent_get_path(agent));
224                 } else {
225                         BT_INFO("Plugin Headed not Enabled");
226                         GVariant *param = NULL;
227                         param = g_variant_new("(iss)", ret, address, name);
228                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PIN_REQUEST, param);
229                 }
230         }
231
232 done:
233         g_variant_unref(reply);
234         g_variant_unref(reply_temp);
235         g_free(address);
236         g_free(name);
237         __bt_agent_release_memory();
238         BT_DBG("-");
239
240         return TRUE;
241 }
242
243 static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
244 {
245         gchar *address = NULL;
246         gchar *name = NULL;
247         unsigned char auth_info[5] = {0, };
248         GVariant *reply = NULL;
249         GVariant *reply_temp = NULL;
250         GVariant *tmp_value;
251         int ret = BLUETOOTH_ERROR_NONE;
252 #ifdef TIZEN_FEATURE_BT_DPM
253         int pairing_state = DPM_STATUS_ERROR;
254 #endif
255
256         BT_DBG("+");
257
258 #ifdef TIZEN_FEATURE_BT_DPM
259         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
260         if (pairing_state == DPM_RESTRICTED) {
261                 BT_ERR("Not allow to pair the device");
262                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
263                 __bt_agent_release_memory();
264                 return TRUE;
265         }
266 #endif
267
268         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
269
270         if (reply_temp == NULL) {
271                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
272                                              NULL);
273                 goto done;
274         }
275
276         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
277
278         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
279         g_variant_get(tmp_value, "s", &address);
280         G_VARIANT_UNREF(tmp_value);
281         if (!address) {
282                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
283                 goto done;
284         }
285
286         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
287         g_variant_get(tmp_value, "s", &name);
288         G_VARIANT_UNREF(tmp_value);
289         if (!name)
290                 name = g_strdup(address);
291
292         __bt_get_auth_info(reply, (char *)auth_info);
293
294         if (headed_plugin_info->plugin_headed_enabled) {
295                 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, auth_info,
296                                 NULL, NULL, _gap_agent_get_path(agent));
297         } else {
298                 BT_INFO("Plugin Headed not Enabled");
299                 GVariant *param = NULL;
300                 param = g_variant_new("(iss)", ret, address, name);
301                 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PASSKEY_REQUEST, param);
302         }
303
304
305 done:
306         g_variant_unref(reply);
307         g_variant_unref(reply_temp);
308         g_free(address);
309         g_free(name);
310         __bt_agent_release_memory();
311
312         BT_DBG("-");
313         return TRUE;
314 }
315
316 static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device,
317                                                                 guint passkey)
318 {
319         gchar *address = NULL;
320         gchar *name = NULL;
321         unsigned char auth_info[5] = {0, };
322         char *str_passkey;
323         GVariant *reply = NULL;
324         GVariant *reply_temp = NULL;
325         GVariant *tmp_value = NULL;
326         int ret = BLUETOOTH_ERROR_NONE;
327
328         BT_DBG("+");
329
330         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
331         if (reply_temp == NULL) {
332                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
333                                              NULL);
334                 goto done;
335         }
336
337         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
338
339         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
340         g_variant_get(tmp_value, "s", &address);
341         G_VARIANT_UNREF(tmp_value);
342         if (!address) {
343                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
344                 goto done;
345         }
346
347         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
348         g_variant_get(tmp_value, "s", &name);
349         G_VARIANT_UNREF(tmp_value);
350         if (!name)
351                 name = g_strdup(address);
352
353         __bt_get_auth_info(reply, (char *)auth_info);
354
355         str_passkey = g_strdup_printf("%06d", passkey);
356
357         GVariant *param = NULL;
358         param = g_variant_new("(ss)", address, str_passkey);
359
360         if (passkey_watcher) {
361                 BT_INFO("Send passkey to %s", passkey_watcher);
362                 _bt_send_event_to_dest(passkey_watcher, BT_ADAPTER_EVENT,
363                                 BLUETOOTH_EVENT_PASSKEY_NOTIFICATION, param);
364         } else {
365                 if (headed_plugin_info->plugin_headed_enabled) {
366                         BT_INFO("Plugin Headed Enabled");
367                         headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
368                                         auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
369                 } else {
370                         BT_INFO("Plugin Headed not Enabled");
371                         GVariant *param = NULL;
372                         param = g_variant_new("(isss)", ret, address, name, str_passkey);
373                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
374                 }
375         }
376
377         g_free(str_passkey);
378
379 done:
380         g_variant_unref(reply);
381         g_variant_unref(reply_temp);
382         g_free(address);
383         g_free(name);
384         __bt_agent_release_memory();
385
386         BT_DBG("-");
387         return TRUE;
388 }
389
390 static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
391                                                                 guint passkey)
392 {
393         gchar *address = NULL;
394         gchar *name = NULL;
395         unsigned char auth_info[5] = {0, };
396         char str_passkey[7];
397         GVariant *reply_temp = NULL;
398         GVariant *reply = NULL;
399         GVariant *tmp_value;
400         int ret = BLUETOOTH_ERROR_NONE;
401 #ifdef TIZEN_FEATURE_BT_DPM
402                 int pairing_state = DPM_STATUS_ERROR;
403 #endif
404         BT_DBG("+ passkey[%.6d]", passkey);
405
406 #ifdef TIZEN_FEATURE_BT_DPM
407         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
408         if (pairing_state == DPM_RESTRICTED) {
409                 BT_ERR("Not allow to pair the device");
410                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
411                 __bt_agent_release_memory();
412                 return TRUE;
413         }
414 #endif
415
416         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
417
418         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
419
420         if (reply_temp == NULL) {
421                 BT_ERR("Device doesn't exist");
422                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
423                                              NULL);
424                 goto done;
425         }
426
427         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
428
429         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
430         g_variant_get(tmp_value, "s", &address);
431         G_VARIANT_UNREF(tmp_value);
432         if (!address) {
433                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
434                 goto done;
435         }
436
437         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
438         g_variant_get(tmp_value, "s", &name);
439         G_VARIANT_UNREF(tmp_value);
440         if (!name)
441                 name = g_strdup(address);
442         __bt_get_auth_info(reply, (char *)auth_info);
443
444         if (headed_plugin_info->plugin_headed_enabled) {
445                 BT_DBG("LAUNCH SYSPOPUP");
446                 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
447                                 auth_info, str_passkey, NULL,
448                                 _gap_agent_get_path(agent));
449         } else {
450                 BT_DBG("Headless Confirmation");
451                 GVariant *param = NULL;
452                 param = g_variant_new("(isss)", ret, address, name, str_passkey);
453                 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PASSKEY_CONFIRM_REQUEST, param);
454         }
455
456 done:
457         g_variant_unref(reply);
458         g_variant_unref(reply_temp);
459         g_free(address);
460         g_free(name);
461         __bt_agent_release_memory();
462         BT_DBG("-");
463
464         return TRUE;
465 }
466
467 static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address)
468 {
469         BT_DBG("On Going Pairing is cancelled by remote\n");
470
471         if (headed_plugin_info->plugin_headed_enabled)
472                 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
473
474         __bt_agent_release_memory();
475
476         return TRUE;
477 }
478
479 static gboolean __a2dp_authorize_request_check(void)
480 {
481         /* Check for existing Media device to disconnect */
482         return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
483 }
484
485 static gboolean __bt_agent_is_hid_device_connectable(void)
486 {
487         GDBusProxy *proxy = NULL;
488         GVariant *reply = NULL;
489         GError *err = NULL;
490         gboolean connectable = FALSE;
491
492         proxy = _bt_gdbus_get_hid_agent_proxy();
493         retv_if(proxy == NULL, FALSE);
494
495         reply = g_dbus_proxy_call_sync(proxy, "IsHidConnectable", NULL,
496                                 G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &err);
497         if (reply == NULL) {
498                 BT_ERR("Error returned in method call");
499                 if (err != NULL) {
500                         BT_ERR("Error message = %s", err->message);
501                         g_error_free(err);
502                 }
503                 connectable = FALSE;
504         } else {
505                 g_variant_get(reply, "(b)", &connectable);
506                 g_variant_unref(reply);
507         }
508         g_object_unref(proxy);
509
510         BT_INFO("HID Device is %s",
511                         connectable ? "Connectable" : "Non-connectable");
512
513         return connectable;
514 }
515
516 static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
517                                                         const char *uuid)
518 {
519         gchar *address = NULL;
520         gchar *name = NULL;
521         unsigned char auth_info[5] = {0, };
522         gboolean trust;
523         GVariant *reply = NULL;
524         GVariant *reply_temp = NULL;
525         GVariant *tmp_value;
526         int result = BLUETOOTH_ERROR_NONE;
527         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
528
529         BT_DBG("+");
530
531         /* Check if already Media connection exsist */
532         if (!strcasecmp(uuid, A2DP_UUID)) {
533                 gboolean ret = FALSE;
534
535                 ret = __a2dp_authorize_request_check();
536
537                 if (ret) {
538                         BT_ERR("Already one A2DP device connected \n");
539                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
540                                               NULL);
541                         goto done;
542                 }
543         }
544         /* Check completed */
545
546         if (!strcasecmp(uuid, HID_UUID)) {
547                 gboolean is_connectable = __bt_agent_is_hid_device_connectable();
548                 BT_DBG("Automatically %s authorization for HID",
549                         is_connectable ? "accept" : "reject");
550                 if (is_connectable == TRUE)
551                         gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
552                 else
553                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
554                 goto done;
555         }
556
557         if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
558              !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
559              !strcasecmp(uuid, HFP_HS_UUID) ||
560              !strcasecmp(uuid, HSP_HS_UUID) ||
561              !strcasecmp(uuid, A2DP_UUID) ||
562              !strcasecmp(uuid, HID_DEVICE_UUID) ||
563              !strcasecmp(uuid, SAP_UUID_OLD) ||
564              !strcasecmp(uuid, SAP_UUID_NEW) ||
565              !strcasecmp(uuid, IOTIVITY_UUID) ||
566              !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
567                 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
568                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
569                                               NULL);
570
571                 goto done;
572         }
573
574         if (!strcasecmp(uuid, NAP_UUID) ||
575              !strcasecmp(uuid, GN_UUID) ||
576               !strcasecmp(uuid, BNEP_UUID)) {
577
578                 BT_DBG("Network connection request: %s", uuid);
579                 if (TIZEN_FEATURE_NETWORK_TETHERING_ENABLE) {
580                         if (nap_connected_device_count >=
581                                                 BT_PAN_MAX_CONNECTION) {
582                                 BT_ERR("Max connection exceeded");
583                                 goto fail;
584                         }
585
586                         if (headed_plugin_info->plugin_headed_enabled) {
587                                 if (headed_plugin_info->headed_plugin->bt_is_tethering_enabled() == FALSE) {
588                                         BT_ERR("BT tethering is not enabled");
589                                         goto fail;
590                                 }
591                         }
592                 }
593
594                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
595                                               NULL);
596                 goto done;
597 fail:
598                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
599                       NULL);
600
601                 goto done;
602         }
603
604         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
605         if (reply_temp == NULL) {
606                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
607                                              NULL);
608                 goto done;
609         }
610
611         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
612
613         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
614         g_variant_get(tmp_value, "s", &address);
615         G_VARIANT_UNREF(tmp_value);
616         if (!address) {
617                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
618                 goto done;
619         }
620
621         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
622         g_variant_get(tmp_value, "s", &name);
623         G_VARIANT_UNREF(tmp_value);
624         if (!name)
625                 name = g_strdup(address);
626
627         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
628         g_variant_get(tmp_value, "b", &trust);
629         G_VARIANT_UNREF(tmp_value);
630
631         __bt_get_auth_info(reply, (char *)auth_info);
632
633         BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
634
635         if (strcasecmp(uuid, OPP_UUID) == 0 &&
636              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
637                                         NULL) == TRUE) {
638                 _bt_send_event(BT_OPP_SERVER_EVENT,
639                                 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
640                                 g_variant_new("(iss)", result, address, name));
641
642                 goto done;
643         }
644         /* TODO: MAP? see above */
645
646         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
647                                         (char *)uuid) == TRUE) {
648                 bt_agent_osp_server_t *osp_serv;
649                 osp_serv = _gap_agent_get_osp_server(agent,
650                                                 BT_RFCOMM_SERVER, (char *)uuid);
651
652                 if (osp_serv) {
653                         _bt_send_event(BT_RFCOMM_SERVER_EVENT,
654                                 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
655                                 g_variant_new("(issssn)", result, address, uuid,
656                                                 name, osp_serv->path, osp_serv->fd));
657                 }
658
659                 goto done;
660         }
661
662         if (!strcasecmp(uuid, OPP_UUID))
663                 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
664         else if (!strcasecmp(uuid, PBAP_UUID))
665                 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
666         else if (!strcasecmp(uuid, MAP_UUID))
667                 request_type = BT_AGENT_EVENT_MAP_REQUEST;
668         /* TODO: MAP is already here */
669
670         if (trust || !headed_plugin_info->plugin_headed_enabled) {
671                 BT_INFO("Trusted or Headless device, so authorize\n");
672                 gap_agent_reply_authorize(agent,
673                                 GAP_AGENT_ACCEPT, NULL);
674
675                 goto done;
676         }
677
678         if (headed_plugin_info->plugin_headed_enabled) {
679                 headed_plugin_info->headed_plugin->bt_launch_system_popup(request_type, name, auth_info, NULL, NULL,
680                                         _gap_agent_get_path(agent));
681         }
682
683 done:
684         if (reply)
685                 g_variant_unref(reply);
686
687         if (reply_temp)
688                 g_variant_unref(reply_temp);
689
690         g_free(name);
691         g_free(address);
692         __bt_agent_release_memory();
693         BT_DBG("-");
694
695         return TRUE;
696 }
697
698 static gboolean __authorization_cancel_request(GapAgentPrivate *agent,
699                                                         const char *address)
700 {
701         BT_DBG("On Going Authorization is cancelled by remote\n");
702
703         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
704
705         if (headed_plugin_info->plugin_headed_enabled)
706                 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
707
708         __bt_agent_release_memory();
709
710         return TRUE;
711 }
712
713 void _bt_destroy_agent(void *agent)
714 {
715         if (!agent)
716                 return;
717
718         _gap_agent_reset_dbus((GapAgentPrivate *)agent);
719
720         g_free(agent);
721 }
722
723 void* _bt_create_agent(const char *path, gboolean adapter)
724 {
725         GAP_AGENT_FUNC_CB func_cb;
726         GDBusProxy *adapter_proxy;
727         GapAgentPrivate *agent;
728
729         adapter_proxy = _bt_get_adapter_proxy();
730         if (!adapter_proxy)
731                 return NULL;
732
733         func_cb.pincode_func = __pincode_request;
734         func_cb.display_func = __display_request;
735         func_cb.passkey_func = __passkey_request;
736         func_cb.confirm_func = __confirm_request;
737         func_cb.authorize_func = __authorize_request;
738         func_cb.pairing_cancel_func = __pairing_cancel_request;
739         func_cb.authorization_cancel_func = __authorization_cancel_request;
740
741         /* Allocate memory*/
742         agent = g_new0(GapAgentPrivate, 1);
743
744         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
745
746         if (adapter) {
747                 if (!_gap_agent_register(agent)) {
748                         _bt_destroy_agent(agent);
749                         agent = NULL;
750                 }
751         }
752
753         return agent;
754 }
755
756 gboolean _bt_agent_register_osp_server(const gint type,
757                 const char *uuid, char *path, int fd)
758 {
759         void *agent = _bt_get_adapter_agent();
760         if (!agent)
761                 return FALSE;
762
763         return _gap_agent_register_osp_server(agent, type, uuid, path, fd);
764
765 }
766
767 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
768 {
769         void *agent = _bt_get_adapter_agent();
770
771         if (!agent)
772                 return FALSE;
773
774         return _gap_agent_unregister_osp_server(agent, type, uuid);
775 }
776
777 gboolean _bt_agent_reply_authorize(gboolean accept)
778 {
779         guint accept_val;
780
781         void *agent = _bt_get_adapter_agent();
782         if (!agent)
783                 return FALSE;
784
785         accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
786
787         return gap_agent_reply_authorize(agent, accept_val, NULL);
788 }
789
790 gboolean _bt_agent_is_canceled(void)
791 {
792         void *agent = _bt_get_adapter_agent();
793         if (!agent)
794                 return FALSE;
795
796         return _gap_agent_is_canceled(agent);
797 }
798
799 void _bt_agent_set_canceled(gboolean value)
800 {
801         void *agent = _bt_get_adapter_agent();
802         if (!agent)
803                 return;
804
805         return _gap_agent_set_canceled(agent, value);
806 }
807
808 int _bt_agent_reply_cancellation(void)
809 {
810         void *agent = _bt_get_adapter_agent();
811
812         if (!agent)
813                 return BLUETOOTH_ERROR_INTERNAL;
814
815         if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
816                 BT_ERR("Fail to reply agent");
817                 return BLUETOOTH_ERROR_INTERNAL;
818         }
819
820         return BLUETOOTH_ERROR_NONE;
821 }
822
823 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
824 {
825         switch ((dev_class & 0x1f00) >> 8) {
826         case 0x05:
827                 switch ((dev_class & 0xc0) >> 6) {
828                 case 0x01:
829                         /* input-keyboard" */
830                         return TRUE;
831                 }
832                 break;
833         }
834
835         return FALSE;
836 }
837
838 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
839                                                         const char *address)
840 {
841         char *pch;
842         char *last;
843
844         pch = strtok_r(buffer, "= ,", &last);
845
846         if (pch == NULL)
847                 return FALSE;
848
849         while ((pch = strtok_r(NULL, ",", &last))) {
850                 if (0 == g_strcmp0(pch, address)) {
851                         BT_DBG("Match found\n");
852                         return TRUE;
853                 }
854         }
855         return FALSE;
856 }
857
858 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
859                                                 const char *partial_name)
860 {
861         char *pch;
862         char *last;
863
864         pch = strtok_r(buffer, "= ,", &last);
865
866         if (pch == NULL)
867                 return FALSE;
868
869         while ((pch = strtok_r(NULL, ",", &last))) {
870                 if (g_str_has_prefix(partial_name, pch)) {
871                         BT_DBG("Match found\n");
872                         return TRUE;
873                 }
874         }
875         return FALSE;
876 }
877
878 static gboolean __bt_agent_is_device_blacklist(const char *address,
879                                                         const char *name)
880 {
881         char *buffer;
882         char **lines;
883         int i;
884         FILE *fp;
885         long size;
886         size_t result;
887
888         BT_DBG("+");
889
890         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
891
892         if (fp == NULL) {
893                 BT_ERR("Unable to open blacklist file");
894                 return FALSE;
895         }
896
897         fseek(fp, 0, SEEK_END);
898         size = ftell(fp);
899         if (size <= 0) {
900                 BT_DBG("size is not a positive number");
901                 fclose(fp);
902                 return FALSE;
903         }
904
905         rewind(fp);
906
907         buffer = g_malloc0(sizeof(char) * size);
908         result = fread((char *)buffer, 1, size, fp);
909         fclose(fp);
910         if (result != size) {
911                 BT_ERR("Read Error");
912                 g_free(buffer);
913                 return FALSE;
914         }
915
916         BT_DBG("Buffer = %s", buffer);
917
918         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
919         g_free(buffer);
920
921         if (lines == NULL) {
922                 BT_ERR("No lines in the file");
923                 return FALSE;
924         }
925
926         for (i = 0; lines[i] != NULL; i++) {
927                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
928                         if (__bt_agent_find_device_by_address_exactname(
929                                                 lines[i], address))
930                                 goto done;
931                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
932                         if (__bt_agent_find_device_by_address_exactname(
933                                                 lines[i], name))
934                                 goto done;
935                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
936                         if (__bt_agent_find_device_by_partial_name(lines[i],
937                                                                 name))
938                                 goto done;
939                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
940                         if (__bt_agent_find_device_by_address_exactname(
941                                                 lines[i], address))
942                                 goto done;
943         }
944         g_strfreev(lines);
945         BT_DBG("-");
946         return FALSE;
947 done:
948         BT_DBG("Found the device");
949         g_strfreev(lines);
950         return TRUE;
951 }
952
953 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
954                                 const gchar *address, const gchar *name)
955 {
956         gboolean is_headset = FALSE;
957         gboolean is_mouse = FALSE;
958         char lap_address[BT_LOWER_ADDRESS_LENGTH];
959
960         BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
961
962         if (address == NULL)
963                 return FALSE;
964
965         switch ((dev_class & 0x1f00) >> 8) {
966         case 0x04:
967                 switch ((dev_class & 0xfc) >> 2) {
968                 case 0x01:
969                 case 0x02:
970                         /* Headset */
971                         is_headset = TRUE;
972                         break;
973                 case 0x06:
974                         /* Headphone */
975                         is_headset = TRUE;
976                         break;
977                 case 0x0b:      /* VCR */
978                 case 0x0c:      /* Video Camera */
979                 case 0x0d:      /* Camcorder */
980                         break;
981                 default:
982                         /* Other audio device */
983                         is_headset = TRUE;
984                         break;
985                 }
986                 break;
987         case 0x05:
988                 switch (dev_class & 0xff) {
989                 case 0x80:  /* 0x80: Pointing device(Mouse) */
990                         is_mouse = TRUE;
991                         break;
992
993                 case 0x40: /* 0x40: input device (BT keyboard) */
994
995                         /* Get the LAP(Lower Address part) */
996                         g_strlcpy(lap_address, address, sizeof(lap_address));
997
998                         /* Need to Auto pair the blacklisted Keyboard */
999                         if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
1000                                 BT_DBG("Device is not black listed\n");
1001                                 return FALSE;
1002                         } else {
1003                                 BT_ERR("Device is black listed\n");
1004                                 return TRUE;
1005                         }
1006                 }
1007         }
1008
1009         if ((!is_headset) && (!is_mouse))
1010                 return FALSE;
1011
1012         /* Get the LAP(Lower Address part) */
1013         g_strlcpy(lap_address, address, sizeof(lap_address));
1014
1015         BT_DBG("Device address = %s\n", address);
1016         BT_DBG("Address 3 byte = %s\n", lap_address);
1017
1018         if (__bt_agent_is_device_blacklist(lap_address, name)) {
1019                 BT_ERR("Device is black listed\n");
1020                 return FALSE;
1021         }
1022
1023         return TRUE;
1024 }
1025
1026 static int __bt_agent_generate_passkey(char *passkey, int size)
1027 {
1028         int i;
1029         ssize_t len;
1030         int random_fd;
1031         unsigned int value = 0;
1032
1033         if (passkey == NULL)
1034                 return -1;
1035
1036         if (size <= 0)
1037                 return -1;
1038
1039         random_fd = open("/dev/urandom", O_RDONLY);
1040
1041         if (random_fd < 0)
1042                 return -1;
1043
1044         for (i = 0; i < size; i++) {
1045                 len = read(random_fd, &value, sizeof(value));
1046                 if (len > 0)
1047                         passkey[i] = '0' + (value % 10);
1048         }
1049
1050         close(random_fd);
1051
1052         BT_DBG("passkey: %s", passkey);
1053
1054         return 0;
1055 }
1056
1057 int _bt_set_passkey_notification(const char *sender, gboolean enable)
1058 {
1059         BT_INFO("Set passkey notification(sender:%s, %s)",
1060                         sender, enable ? "Enable" : "Disable");
1061
1062         g_free(passkey_watcher);
1063         if (enable == TRUE)
1064                 passkey_watcher = g_strdup(sender);
1065         else
1066                 passkey_watcher = NULL;
1067
1068         return BLUETOOTH_ERROR_NONE;
1069 }