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