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