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