077e69613108eb3bddee6d6bb9453b705bf732cc
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-agent.c
1 /*
2  * BLUETOOTH HAL
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <malloc.h>
26 #include <syspopup_caller.h>
27 #include <vconf.h>
28 #include <bundle.h>
29 #include <bundle_internal.h>
30 #include <eventsystem.h>
31
32 #include <dbus/dbus-glib.h>
33 #include <dbus/dbus.h>
34 #include <glib.h>
35 #include <gio/gio.h>
36 #include <dlog.h>
37 #include <vconf.h>
38
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <sys/mman.h>
43
44 /* BT HAL Headers */
45 #include "bt-hal.h"
46 #include "bt-hal-log.h"
47 #include "bt-hal-msg.h"
48 #include "bt-hal-internal.h"
49 #include "bt-hal-utils.h"
50 #include "bt-hal-event-receiver.h"
51 #include "bt-hal-dbus-common-utils.h"
52
53 #include "bt-hal-adapter-dbus-handler.h"
54 #include "bt-hal-event-receiver.h"
55
56 #include <bt-hal-agent.h>
57 #include <bt-hal-gap-agent.h>
58 #include <bt-hal-dbus-common-utils.h>
59
60 #define BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE (APP_SYSCONFDIR"/auto-pair-blacklist")
61 #define BT_HAL_AGENT_NEW_LINE "\r\n"
62 #define BUF_SIZE                256
63 #define PAGE_SIZE               (1 << 12)
64 #define _ALIGN_UP(addr, size)    (((addr)+((size)-1))&(~((size)-1)))
65 #define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
66 #define PAGE_ALIGN(addr)        _ALIGN_DOWN(addr, PAGE_SIZE)
67 #define BT_HAL_PIN_MAX_LENGTH 16
68 #define BT_HAL_PASSKEY_MAX_LENGTH 4
69 #define BT_HAL_LOWER_ADDRESS_LENGTH 9
70 #define BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
71 #define BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT 3
72
73 #define G_VARIANT_UNREF(variant) \
74         g_variant_unref(variant); \
75         variant = NULL
76 #define BT_HAL_MAX_EVENT_STR_LENGTH 50
77
78 static void *adapter_agent = NULL;
79
80 /* Forward delcaration */
81 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
82                 uint32_t cod);
83 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device);
84 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
85                 guint passkey);
86 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device);
87 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
88                 guint passkey);
89 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
90                                                         const char *uuid);
91 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface);
92 static void __bt_hal_agent_release_memory(void);
93 static inline void stack_trim(void);
94
95 #ifdef TIZEN_SYSPOPUP_SUPPORTED
96 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class);
97 static int __bt_hal_device_generate_passkey(char *passkey, int size);
98 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
99                 const gchar *address, const gchar *name);
100 static gboolean __bt_hal_device_is_device_blacklisted(const char *address, const char *name);
101 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
102                 const char *address);
103 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
104                 const char *partial_name);
105 static gboolean __bt_hal_agent_system_popup_timer_cb(gpointer user_data);
106 #else
107 static void __bt_hal_send_ssp_request_events(const gchar *address, const gchar *name,
108                 guint passkey, uint32_t cod, unsigned char variant);
109 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid);
110 #endif
111
112 void* _bt_hal_create_agent(const char *path, gboolean adapter)
113 {
114         GAP_AGENT_FUNC_CB func_cb;
115         GDBusProxy *adapter_proxy;
116         GapAgentPrivate *agent;
117
118         DBG("+");
119         adapter_proxy = _bt_get_adapter_proxy();
120         if (!adapter_proxy)
121                 return NULL;
122
123         func_cb.pincode_func = __bt_hal_pincode_request;
124         func_cb.display_func = __bt_hal_display_request;
125         func_cb.passkey_func = __bt_hal_passkey_request;
126         func_cb.confirm_func = __bt_hal_confirm_request;
127         func_cb.authorize_func = __bt_hal_authorize_request;
128         func_cb.pairing_cancel_func = NULL;
129         func_cb.authorization_cancel_func = NULL;
130
131         /* Allocate memory*/
132         agent = g_new0(GapAgentPrivate, 1);
133
134         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
135
136         if (adapter) {
137                 if (!_gap_agent_register(agent)) {
138                         ERR("gap agent registration failed!");
139                         _bt_hal_destroy_agent(agent);
140                         agent = NULL;
141                 }
142         }
143         DBG("-");
144         return agent;
145 }
146
147 void _bt_hal_destroy_agent(void *agent)
148 {
149         DBG("+");
150         if (!agent)
151                 return;
152
153         _gap_agent_reset_dbus((GapAgentPrivate *)agent);
154
155         g_free(agent);
156         DBG("-");
157 }
158
159 gboolean _bt_hal_agent_is_canceled(void)
160 {
161         void *agent = _bt_hal_get_adapter_agent();
162         if (!agent)
163                 return FALSE;
164
165         return _gap_agent_is_canceled(agent);
166 }
167
168 int _bt_hal_agent_reply_cancellation(void)
169 {
170         void *agent = _bt_hal_get_adapter_agent();
171         if (!agent)
172                 return BT_STATUS_FAIL;
173
174         if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
175                 ERR("Fail to reply agent");
176                 return BT_STATUS_FAIL;
177         }
178         DBG("gap agent cancellation done successfully!");
179         return BT_STATUS_SUCCESS;
180
181 }
182
183 void _bt_hal_agent_set_canceled(gboolean value)
184 {
185         void *agent = _bt_hal_get_adapter_agent();
186         if (!agent)
187                 return;
188
189         return _gap_agent_set_canceled(agent, value);
190 }
191
192 void _bt_hal_initialize_adapter_agent(void)
193 {
194         adapter_agent = _bt_hal_create_agent(BT_HAL_ADAPTER_AGENT_PATH, TRUE);
195         if (!adapter_agent) {
196                 ERR("Fail to register agent");
197                 return;
198         }
199 }
200
201 void _bt_hal_destroy_adapter_agent(void)
202 {
203         if (adapter_agent)
204                 _bt_hal_destroy_agent(adapter_agent);
205         adapter_agent = NULL;
206 }
207
208 void* _bt_hal_get_adapter_agent(void)
209 {
210         return adapter_agent;
211 }
212
213 #ifndef TIZEN_SYSPOPUP_SUPPORTED
214 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid)
215 {
216         struct hal_ev_authorize_request ev;
217         memset(&ev, 0, sizeof(ev));
218
219         DBG("Remote Device address [%s]", address);
220
221         _bt_convert_addr_string_to_type(ev.bdaddr, address);
222         ev.service_id = _bt_convert_uuid_string_to_service_id(uuid);
223
224         handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
225         if (event_cb) {
226                 DBG("Sending AUTHORIZE REQUEST");
227                 event_cb(HAL_EV_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
228         }
229
230         DBG("-");
231 }
232 #endif
233
234 /* Legacy Pairing */
235 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
236                 uint32_t cod)
237 {
238         struct hal_ev_pin_request ev;
239         memset(&ev, 0, sizeof(ev));
240
241         DBG("Remote Device address [%s]", address);
242         DBG("Remote Device Name [%s]", name);
243         DBG("Remote Device COD [%u]", cod);
244
245         _bt_convert_addr_string_to_type(ev.bdaddr, address);
246
247         memcpy(ev.name, name, strlen(name));
248         ev.class_of_dev = cod;
249
250         handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
251         if (event_cb) {
252                 DBG("Sending PIN REQUEST");
253                 event_cb(HAL_EV_PIN_REQUEST, (void*)&ev, sizeof(ev));
254         }
255
256         DBG("-");
257 }
258
259 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
260 {
261         uint32_t device_class;
262         const gchar *address;
263         const gchar *name;
264         GVariant *reply = NULL;
265         GVariant *reply_temp = NULL;
266         GVariant *tmp_value;
267         DBG("+");
268
269         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
270
271         if (reply_temp == NULL) {
272                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
273                                 NULL);
274                 goto done;
275         }
276
277         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
278
279         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
280         g_variant_get(tmp_value, "u", &device_class);
281         G_VARIANT_UNREF(tmp_value);
282
283         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
284         g_variant_get(tmp_value, "s", &address);
285         G_VARIANT_UNREF(tmp_value);
286
287         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
288         g_variant_get(tmp_value, "s", &name);
289         G_VARIANT_UNREF(tmp_value);
290
291         if (!name)
292                 name = address;
293 #ifdef TIZEN_SYSPOPUP_SUPPORTED
294         if (__bt_hal_device_is_hid_keyboard(device_class)) {
295                 DBG("Device is HID Keyboard");
296                 char str_passkey[BT_HAL_PASSKEY_MAX_LENGTH + 1] = { 0 };
297                 if (__bt_hal_device_generate_passkey(str_passkey,
298                                         BT_HAL_PASSKEY_MAX_LENGTH) != 0) {
299                         gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
300                                         "", NULL);
301                         goto done;
302                 }
303                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
304                                 str_passkey, NULL);
305
306                 DBG("Launch BT Syspopup");
307                 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
308                                 name, str_passkey, NULL,
309                                 _gap_agent_get_path(agent));
310         } else if (!__bt_hal_device_is_auto_response(device_class, address, name)) {
311                 DBG("Device is not of AUto response class, Show PIN Entry");
312                 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PIN_REQUEST, name, NULL,
313                                 NULL, _gap_agent_get_path(agent));
314         } else {
315                 DBG("Device is of Type Auto response, send event to HAL");
316                 __bt_hal_send_pin_request_event(address, name, device_class);
317         }
318 #else
319         DBG("PIN CODE request, device class [%u]", device_class);
320         __bt_hal_send_pin_request_event(address, name, device_class);
321 #endif
322
323 done:
324         g_variant_unref(reply);
325         g_variant_unref(reply_temp);
326         __bt_hal_agent_release_memory();
327         DBG("-");
328
329         return TRUE;
330 }
331
332
333 /* BT_SSP_VARIANT_PASSKEY_CONFIRMATION */
334 /* BT_SSP_VARIANT_PASSKEY_NOTIFICATION */
335 /* BT_SSP_VARIANT_PASSKEY_ENTRY */
336 /* BT_SSP_VARIANT_CONSENT */
337
338 #ifndef TIZEN_SYSPOPUP_SUPPORTED
339 static void __bt_hal_send_ssp_request_events(const gchar *address,
340                 const gchar *name,
341                 guint passkey,
342                 uint32_t cod,
343                 unsigned char variant)
344 {
345         struct hal_ev_ssp_request ev;
346         memset(&ev, 0, sizeof(ev));
347         DBG("sizeof ev [%d]", sizeof(ev));
348
349         DBG("Remote Device address [%s]", address);
350         DBG("Remote Device Name [%s]", name);
351         DBG("Remote Device passkey [%d]", passkey);
352         DBG("Remote Device pairing variant [0x%x]", variant);
353         DBG("Remote Device cod [%d]", cod);
354
355         _bt_convert_addr_string_to_type(ev.bdaddr, address);
356
357         memcpy(ev.name, name, strlen(name));
358         ev.class_of_dev = cod;
359         ev.pairing_variant = variant;
360         ev.passkey = passkey;
361
362         handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
363         if (event_cb) {
364                 DBG("Sending SSP type [%d]", variant);
365                 event_cb(HAL_EV_SSP_REQUEST, (void*)&ev, sizeof(ev));
366         }
367
368         DBG("-");
369 }
370 #endif
371
372 /* SSP */
373 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
374                 guint passkey)
375 {
376         const gchar *address;
377         const gchar *name;
378         char *str_passkey;
379         uint32_t device_class;
380         GVariant *reply = NULL;
381         GVariant *reply_temp = NULL;
382         GVariant *tmp_value = NULL;
383         DBG("+");
384
385         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
386         if (reply_temp == NULL) {
387                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
388                                 NULL);
389                 goto done;
390         }
391
392         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
393
394         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
395         g_variant_get(tmp_value, "s", &address);
396         G_VARIANT_UNREF(tmp_value);
397         if (!address) {
398                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
399                 goto done;
400         }
401
402         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
403         g_variant_get(tmp_value, "s", &name);
404         G_VARIANT_UNREF(tmp_value);
405
406         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
407         g_variant_get(tmp_value, "u", &device_class);
408         G_VARIANT_UNREF(tmp_value);
409
410         if (!name)
411                 name = address;
412
413         str_passkey = g_strdup_printf("%d", passkey);
414
415 #ifdef TIZEN_SYSPOPUP_SUPPORTED
416         DBG("Launch BT Syspopup: KEYBOARD_PASSKEY_REQUEST");
417         _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
418                         str_passkey, NULL,
419                         _gap_agent_get_path(agent));
420 #else
421
422         __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
423                         BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
424 #endif
425
426         g_free(str_passkey);
427 done:
428         g_variant_unref(reply);
429         g_variant_unref(reply_temp);
430         __bt_hal_agent_release_memory();
431
432         DBG("-");
433         return TRUE;
434 }
435
436 /* SSP */
437 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
438 {
439         const gchar *address;
440         const gchar *name;
441         uint32_t device_class;
442         GVariant *reply = NULL;
443         GVariant *reply_temp = NULL;
444         GVariant *tmp_value;
445         DBG("+");
446
447         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
448
449         if (reply_temp == NULL) {
450                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
451                                 NULL);
452                 goto done;
453         }
454
455         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
456
457         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
458         g_variant_get(tmp_value, "s", &address);
459         G_VARIANT_UNREF(tmp_value);
460         if (!address) {
461                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
462                 goto done;
463         }
464
465         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
466         g_variant_get(tmp_value, "s", &name);
467         G_VARIANT_UNREF(tmp_value);
468
469         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
470         g_variant_get(tmp_value, "u", &device_class);
471         G_VARIANT_UNREF(tmp_value);
472
473         if (!name)
474                 name = address;
475 #ifdef TIZEN_SYSPOPUP_SUPPORTED
476         DBG("Launch BT Syspopup: PASSKEY_REQUEST");
477         _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL,
478                         _gap_agent_get_path(agent));
479 #else
480         __bt_hal_send_ssp_request_events(address, name, 0, device_class,
481                         BT_SSP_VARIANT_PASSKEY_ENTRY);
482 #endif
483
484 done:
485         g_variant_unref(reply);
486         g_variant_unref(reply_temp);
487         __bt_hal_agent_release_memory();
488
489         DBG("-");
490         return TRUE;
491 }
492
493 /*ssp*/
494 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
495                 guint passkey)
496 {
497         const gchar *address;
498         const gchar *name;
499         char str_passkey[7];
500         uint32_t device_class;
501         GVariant *reply_temp = NULL;
502         GVariant *reply = NULL;
503         GVariant *tmp_value;
504         DBG("+ passkey[%.6d]", passkey);
505         DBG("Agent Path [%s]", agent->path);
506
507         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
508
509         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
510
511         if (reply_temp == NULL) {
512                 ERR("####Device doesn't exist####");
513                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
514                                 NULL);
515                 goto done;
516         }
517         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
518
519         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
520         g_variant_get(tmp_value, "s", &address);
521         G_VARIANT_UNREF(tmp_value);
522
523         tmp_value = g_variant_lookup_value (reply, "Name", G_VARIANT_TYPE_STRING);
524         g_variant_get(tmp_value, "s", &name);
525         G_VARIANT_UNREF(tmp_value);
526
527         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
528         g_variant_get(tmp_value, "u", &device_class);
529         G_VARIANT_UNREF(tmp_value);
530
531         if (!name)
532                 name = address;
533 #ifdef TIZEN_WEARABLE
534         uint32_t major_class;
535
536
537         major_class = (device_class & 0x1f00) >> 8;
538
539         if (major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) {
540                 DBG("Audio device. Launch passkey pop-up");
541                 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
542                                 str_passkey, NULL, _gap_agent_get_path(agent));
543                 goto done;
544         }
545
546         if (__is_reset_required(address)) {
547                 DBG("Launch system reset pop-up");
548                 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_SYSTEM_RESET_REQUEST, name,
549                                 NULL, NULL, _gap_agent_get_path(agent));
550         } else {
551                 DBG("Launch passkey pop-up");
552                 _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED, name,
553                                 str_passkey, NULL, _gap_agent_get_path(agent));
554
555                 gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
556         }
557 #else
558
559 #ifdef TIZEN_SYSPOPUP_SUPPORTED
560         DBG("Launch BT Syspopup");
561         DBG("Name [%s]", name);
562         DBG("Passkey [%s]", str_passkey);
563         _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
564                         str_passkey, NULL,
565                         _gap_agent_get_path(agent));
566 #else
567         __bt_hal_send_ssp_request_events(address, name, passkey,
568                         device_class, BT_SSP_VARIANT_PASSKEY_CONFIRMATION);
569 #endif //TIZEN_SYSPOPUP_SUPPORTED
570 #endif //TIZEN_WEARABLE
571
572 done:
573         g_variant_unref(reply);
574         g_variant_unref(reply_temp);
575         __bt_hal_agent_release_memory();
576         DBG("-");
577         return TRUE;
578 }
579
580 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
581                                                         const char *uuid)
582 {
583         const gchar *address;
584         const gchar *name;
585         gboolean trust;
586         gboolean paired;
587         GVariant *reply = NULL;
588         GVariant *reply_temp = NULL;
589         GVariant *tmp_value;
590
591         DBG("Authorize Request from Bluez Stack: UUID [%s]", uuid);
592
593         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
594         if (reply_temp == NULL) {
595                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
596                 goto done;
597         }
598
599         g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
600
601         tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
602         g_variant_get(tmp_value, "s", &address);
603         G_VARIANT_UNREF(tmp_value);
604         if (!address) {
605                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
606                 goto done;
607         }
608
609         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
610         g_variant_get(tmp_value, "s", &name);
611         G_VARIANT_UNREF(tmp_value);
612         if (!name)
613                 name = address;
614
615         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
616         g_variant_get(tmp_value, "b", &trust);
617         G_VARIANT_UNREF(tmp_value);
618
619         tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
620         g_variant_get(tmp_value, "b", &paired);
621         G_VARIANT_UNREF(tmp_value);
622         if ((paired == FALSE) && (trust == FALSE)) {
623                 ERR("No paired & No trusted device");
624                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
625                 goto done;
626         }
627
628         INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
629
630         if (trust) {
631                 INFO("Trusted device, so authorize\n");
632                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
633                 goto done;
634         } else {
635                 INFO("Device is not Trusted, so prompt user to accept or reject authorization \n");
636         }
637
638         /*
639          * TODO: Handling for authorization request for different profiles will be
640          * implemented while profiles support is added. For now send all the request
641          * to bt-service or, launch bt-syspopup.
642          */
643 #ifdef TIZEN_SYSPOPUP_SUPPORTED
644         DBG("Launch Syspopup: AUTHORIZE_REQUEST");
645         _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST,
646                         name, NULL, NULL, _gap_agent_get_path(agent));
647 #else
648         __bt_hal_send_authorize_request_event(address, uuid);
649 #endif
650
651 done:
652         g_variant_unref(reply);
653         g_variant_unref(reply_temp);
654         __bt_hal_agent_release_memory();
655
656         DBG("-");
657         return TRUE;
658 }
659
660 #ifdef TIZEN_SYSPOPUP_SUPPORTED
661 int _bt_hal_launch_system_popup(bt_hal_agent_event_type_t event_type,
662                 const char *device_name,
663                 char *passkey,
664                 const char *filename,
665                 const char *agent_path)
666 {
667         int ret;
668         bundle *b;
669         char event_str[BT_HAL_MAX_EVENT_STR_LENGTH + 1];
670         DBG("+");
671
672         b = bundle_create();
673         if (!b) {
674                 DBG("Launching system popup failed");
675                 return -1;
676         }
677
678         bundle_add(b, "device-name", device_name);
679         bundle_add(b, "passkey", passkey);
680         bundle_add(b, "file", filename);
681         bundle_add(b, "agent-path", agent_path);
682
683         switch (event_type) {
684                 case BT_HAL_AGENT_EVENT_PIN_REQUEST:
685                         g_strlcpy(event_str, "pin-request", sizeof(event_str));
686                         break;
687
688                 case BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
689                         g_strlcpy(event_str, "passkey-confirm-request",
690                                         sizeof(event_str));
691                         break;
692
693                 case BT_HAL_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED:
694                         g_strlcpy(event_str, "passkey-auto-accepted",
695                                         sizeof(event_str));
696                         break;
697
698                 case BT_HAL_AGENT_EVENT_PASSKEY_REQUEST:
699                         g_strlcpy(event_str, "passkey-request", sizeof(event_str));
700                         break;
701
702                 case BT_HAL_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
703                         g_strlcpy(event_str, "passkey-display-request",
704                                         sizeof(event_str));
705                 case BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST:
706                         g_strlcpy(event_str, "authorize-request",
707                                         sizeof(event_str));
708                         break;
709
710                 case BT_HAL_AGENT_EVENT_CONFIRM_MODE_REQUEST:
711                         g_strlcpy(event_str, "confirm-mode-request",
712                                         sizeof(event_str));
713                         break;
714
715                 case BT_HAL_AGENT_EVENT_FILE_RECEIVED:
716                         g_strlcpy(event_str, "file-received", sizeof(event_str));
717                         break;
718
719                 case BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
720                         g_strlcpy(event_str, "keyboard-passkey-request",
721                                         sizeof(event_str));
722                         break;
723
724                 case BT_HAL_AGENT_EVENT_TERMINATE:
725                         g_strlcpy(event_str, "terminate", sizeof(event_str));
726                         break;
727
728                 case BT_HAL_AGENT_EVENT_EXCHANGE_REQUEST:
729                         g_strlcpy(event_str, "exchange-request", sizeof(event_str));
730                         break;
731
732                 case BT_HAL_AGENT_EVENT_PBAP_REQUEST:
733                         g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
734                         break;
735
736                 case BT_HAL_AGENT_EVENT_MAP_REQUEST:
737                         g_strlcpy(event_str, "message-request", sizeof(event_str));
738                         break;
739 #ifdef TIZEN_WEARABLE
740                 case BT_HAL_AGENT_EVENT_SYSTEM_RESET_REQUEST:
741                         __bt_register_popup_event_signal();
742                         g_strlcpy(event_str, "system-reset-request", sizeof(event_str));
743                         break;
744 #endif
745
746                 case BT_HAL_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE:
747                         g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str));
748                         break;
749
750                 default:
751                         DBG("Invalid event type");
752                         bundle_free(b);
753                         return -1;
754
755         }
756
757         bundle_add(b, "event-type", event_str);
758
759         ret = syspopup_launch("bt-syspopup", b);
760         if (0 > ret) {
761                 DBG("Popup launch failed...retry %d", ret);
762
763                 g_timeout_add(BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
764                                 (GSourceFunc)__bt_hal_agent_system_popup_timer_cb, b);
765         } else {
766                 bundle_free(b);
767         }
768
769         DBG("_bt_agent_launch_system_popup");
770         return 0;
771 }
772
773 static gboolean __bt_hal_agent_system_popup_timer_cb(gpointer user_data)
774 {
775         int ret;
776         static int retry_count;
777         bundle *b = (bundle *)user_data;
778         if (user_data == NULL)
779                 return  FALSE;
780
781         ++retry_count;
782
783         ret = syspopup_launch("bt-syspopup", b);
784         if (ret < 0) {
785                 DBG("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..",
786                                 ret, retry_count);
787                 if (retry_count >= BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT) {
788                         DBG("Sorry!! Max retry %d reached", retry_count);
789                         bundle_free(b);
790                         retry_count = 0;
791                         return FALSE;
792                 }
793         } else {
794                 DBG("Hurray!! Finally Popup launched");
795                 retry_count = 0;
796                 bundle_free(b);
797         }
798
799         return (ret < 0) ? TRUE : FALSE;
800 }
801
802 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class)
803 {
804         switch ((dev_class & 0x1f00) >> 8) {
805                 case 0x05:
806                         switch ((dev_class & 0xc0) >> 6) {
807                                 case 0x01:
808                                         /* input-keyboard" */
809                                         return TRUE;
810                         }
811                         break;
812         }
813
814         return FALSE;
815 }
816
817 static int __bt_hal_device_generate_passkey(char *passkey, int size)
818 {
819         int i;
820         ssize_t len;
821         int random_fd;
822         unsigned int value = 0;
823
824         if (passkey == NULL)
825                 return -1;
826
827         if (size <= 0)
828                 return -1;
829
830         random_fd = open("/dev/urandom", O_RDONLY);
831
832         if (random_fd < 0)
833                 return -1;
834
835         for (i = 0; i < size; i++) {
836                 len = read(random_fd, &value, sizeof(value));
837                 if (len > 0)
838                         passkey[i] = '0' + (value % 10);
839         }
840
841         close(random_fd);
842
843         DBG("passkey: %s", passkey);
844
845         return 0;
846 }
847
848 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
849                 const char *address)
850 {
851         char *pch;
852         char *last;
853
854         pch = strtok_r(buffer, "= ,", &last);
855
856         if (pch == NULL)
857                 return FALSE;
858
859         while ((pch = strtok_r(NULL, ",", &last))) {
860                 if (0 == g_strcmp0(pch, address)) {
861                         DBG("Match found\n");
862                         return TRUE;
863                 }
864         }
865         return FALSE;
866 }
867
868 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
869                 const char *partial_name)
870 {
871         char *pch;
872         char *last;
873
874         pch = strtok_r(buffer, "= ,", &last);
875
876         if (pch == NULL)
877                 return FALSE;
878
879         while ((pch = strtok_r(NULL, ",", &last))) {
880                 if (g_str_has_prefix(partial_name, pch)) {
881                         DBG("Match found\n");
882                         return TRUE;
883                 }
884         }
885         return FALSE;
886 }
887
888 static gboolean __bt_hal_device_is_device_blacklisted(const char *address,
889                 const char *name)
890 {
891         char *buffer;
892         char **lines;
893         int i;
894         FILE *fp;
895         long size;
896         size_t result;
897
898         DBG("+");
899
900         fp = fopen(BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
901
902         if (fp == NULL) {
903                 ERR("Unable to open blacklist file");
904                 return FALSE;
905         }
906
907         fseek(fp, 0, SEEK_END);
908         size = ftell(fp);
909         if (size <= 0) {
910                 DBG("size is not a positive number");
911                 fclose(fp);
912                 return FALSE;
913         }
914
915         rewind(fp);
916
917         buffer = g_malloc0(sizeof(char) * size);
918         /* Fix : NULL_RETURNS */
919         if (buffer == NULL) {
920                 ERR("Fail to allocate memory");
921                 fclose(fp);
922                 return FALSE;
923         }
924         result = fread((char *)buffer, 1, size, fp);
925         fclose(fp);
926         if (result != size) {
927                 ERR("Read Error");
928                 g_free(buffer);
929                 return FALSE;
930         }
931
932         DBG("Buffer = %s", buffer);
933
934         lines = g_strsplit_set(buffer, BT_HAL_AGENT_NEW_LINE, 0);
935         g_free(buffer);
936
937         if (lines == NULL) {
938                 ERR("No lines in the file");
939                 return FALSE;
940         }
941
942         for (i = 0; lines[i] != NULL; i++) {
943                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
944                         if (__bt_hal_find_device_by_address_exactname(
945                                                 lines[i], address))
946                                 goto done;
947                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
948                         if (__bt_hal_find_device_by_address_exactname(
949                                                 lines[i], name))
950                                 goto done;
951                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
952                         if (__bt_hal_find_device_by_partial_name(lines[i],
953                                                 name))
954                                 goto done;
955                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
956                         if (__bt_hal_find_device_by_address_exactname(
957                                                 lines[i], address))
958                                 goto done;
959         }
960         g_strfreev(lines);
961         DBG("-");
962         return FALSE;
963 done:
964         DBG("Found the device");
965         g_strfreev(lines);
966         return TRUE;
967 }
968
969 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
970                 const gchar *address, const gchar *name)
971 {
972         gboolean is_headset = FALSE;
973         gboolean is_mouse = FALSE;
974         char lap_address[BT_HAL_LOWER_ADDRESS_LENGTH];
975
976         DBG("bt_agent_is_headset_class, %d +", dev_class);
977
978         if (address == NULL)
979                 return FALSE;
980
981         switch ((dev_class & 0x1f00) >> 8) {
982                 case 0x04:
983                         switch ((dev_class & 0xfc) >> 2) {
984                                 case 0x01:
985                                 case 0x02:
986                                         /* Headset */
987                                         is_headset = TRUE;
988                                         break;
989                                 case 0x06:
990                                         /* Headphone */
991                                         is_headset = TRUE;
992                                         break;
993                                 case 0x0b:      /* VCR */
994                                 case 0x0c:      /* Video Camera */
995                                 case 0x0d:      /* Camcorder */
996                                         break;
997                                 default:
998                                         /* Other audio device */
999                                         is_headset = TRUE;
1000                                         break;
1001                         }
1002                         break;
1003                 case 0x05:
1004                         switch (dev_class & 0xff) {
1005                                 case 0x80:  /* 0x80: Pointing device(Mouse) */
1006                                         is_mouse = TRUE;
1007                                         break;
1008
1009                                 case 0x40: /* 0x40: input device (BT keyboard) */
1010
1011                                         /* Get the LAP(Lower Address part) */
1012                                         g_strlcpy(lap_address, address, sizeof(lap_address));
1013
1014                                         /* Need to Auto pair the blacklisted Keyboard */
1015                                         if (__bt_hal_device_is_device_blacklisted(lap_address, name) != TRUE) {
1016                                                 DBG("Device is not black listed\n");
1017                                                 return FALSE;
1018                                         } else {
1019                                                 ERR("Device is black listed\n");
1020                                                 return TRUE;
1021                                         }
1022                         }
1023         }
1024
1025         if ((!is_headset) && (!is_mouse))
1026                 return FALSE;
1027
1028         /* Get the LAP(Lower Address part) */
1029         g_strlcpy(lap_address, address, sizeof(lap_address));
1030
1031         DBG("Device address = %s\n", address);
1032         DBG("Address 3 byte = %s\n", lap_address);
1033
1034         if (__bt_hal_device_is_device_blacklisted(lap_address, name)) {
1035                 ERR("Device is black listed\n");
1036                 return FALSE;
1037         }
1038
1039         return TRUE;
1040 }
1041 #endif
1042
1043 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface)
1044 {
1045         GError *error = NULL;
1046         GVariant *reply;
1047         DBG("+");
1048         reply = g_dbus_proxy_call_sync(device,
1049                         "GetAll", g_variant_new("(s)", interface),
1050                         G_DBUS_CALL_FLAGS_NONE, -1,
1051                         NULL, &error);
1052         if (reply == NULL) {
1053                 ERR("GetAll dBUS-RPC failed");
1054                 if (error) {
1055                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1056                                         error->code, error->message);
1057                         g_clear_error(&error);
1058                 }
1059                 return NULL;
1060         }
1061
1062         DBG("-");
1063         return reply;
1064 }
1065
1066 static void __bt_hal_agent_release_memory(void)
1067 {
1068         /* Release Malloc Memory*/
1069         malloc_trim(0);
1070
1071         /* Release Stack Memory*/
1072         stack_trim();
1073 }
1074
1075 static inline void stack_trim(void)
1076 {
1077 #ifdef STACK_FLUSH
1078         unsigned int sp;
1079         char buf[BUF_SIZE];
1080         FILE *file;
1081         unsigned int stacktop;
1082         int found = 0;
1083
1084         asm volatile ("mov %0,sp " : "=r"(sp));
1085
1086         sprintf(buf, "/proc/%d/maps", getpid());
1087         file = fopen(buf, "r");
1088         while (fgets(buf, BUF_SIZE, file) != NULL) {
1089                 if (strstr(buf, "[stack]")) {
1090                         found = 1;
1091                         break;
1092                 }
1093         }
1094         fclose(file);
1095
1096         if (found) {
1097                 sscanf(buf, "%x-", &stacktop);
1098                 if (madvise((void *)PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop,
1099                                                                                 MADV_DONTNEED) < 0)
1100                         perror("stack madvise fail");
1101         }
1102 #endif
1103 }