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