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