This patch fixes SVACE issue.
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-gap-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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <vconf.h>
26 #include <vconf-keys.h>
27
28 #include  <bt-hal-gap-agent.h>
29 #include  <bt-hal-agent.h>
30 #include  <bt-hal-internal.h>
31
32 #include "bt-hal.h"
33 #include "bt-hal-log.h"
34 #include "bt-hal-msg.h"
35 #include "bt-hal-utils.h"
36
37 #include "bt-internal-types.h"
38
39 #include <glib.h>
40 #include <gio/gio.h>
41 #include <dlog.h>
42
43 #include "bt-hal-adapter-dbus-handler.h"
44 #include "bt-hal-device-dbus-handler.h"
45 #include "bt-hal-dbus-common-utils.h"
46
47 static GDBusConnection *connection = NULL;
48
49 typedef enum {
50         GAP_AGENT_ERROR_REJECT,
51         GAP_AGENT_ERROR_CANCEL,
52         GAP_AGENT_ERROR_TIMEOUT,
53 } GapAgentError;
54
55 #define AGENT_ALREADY_EXIST 0x24
56
57 #define GAP_UUID "00001800-0000-1000-8000-00805f9b34fb"
58 #define GAP_AGENT_ERROR (gap_agent_error_quark())
59
60 static GQuark gap_agent_error_quark(void)
61 {
62         static GQuark quark = 0;
63         if (!quark)
64                 quark = g_quark_from_static_string("agent");
65
66         return quark;
67 }
68
69
70 /* Forward declaration */
71 static gboolean __gap_agent_unregister(GapAgentPrivate *agent);
72 static GDBusNodeInfo *__bt_service_create_method_node_info
73 (const gchar *introspection_data);
74 static void __bt_gap_agent_method(GDBusConnection *connection,
75                 const gchar *sender,
76                 const gchar *object_path,
77                 const gchar *interface_name,
78                 const gchar *method_name,
79                 GVariant *parameters,
80                 GDBusMethodInvocation *invocation,
81                 gpointer user_data);
82 void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value);
83
84 static gint gap_agent_id = -1;
85
86 #ifdef TIZEN_BT_HAL
87 static void __bt_hal_free_osp_server(gpointer data)
88 {
89         bt_hal_agent_osp_server_t *server = data;
90
91         if (!server)
92                 return;
93
94         g_free(server->uuid);
95         g_free(server->path);
96         g_free(server);
97 }
98
99 static void __bt_hal_gap_agent_remove_osp_servers(GSList *osp_servers)
100 {
101         if (!osp_servers) {
102                 ERR("osp_servers is NULL");
103                 return;
104
105         }
106
107         g_slist_free_full(osp_servers, __bt_hal_free_osp_server);
108 }
109 #endif
110
111 gboolean _gap_agent_register(GapAgentPrivate *agent)
112 {
113         GapAgentPrivate *priv = agent;
114         GDBusProxy *agent_manager;
115         GError *error = NULL;
116         GVariant *reply;
117
118         if (!priv)
119                 return FALSE;
120         if (!connection)
121                 return FALSE;
122
123         if (priv->agent_manager == NULL) {
124                 agent_manager = g_dbus_proxy_new_sync(connection,
125                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
126                                 BT_HAL_BLUEZ_NAME, BT_HAL_BLUEZ_PATH,
127                                 BT_HAL_AGENT_MANAGER_INTERFACE, NULL, &error);
128                 if (!agent_manager) {
129                         if (error) {
130                                 ERR("Unable to create proxy: %s", error->message);
131                                 g_clear_error(&error);
132                         }
133                         return FALSE;
134                 }
135         } else {
136                 agent_manager = priv->agent_manager;
137         }
138
139         reply = g_dbus_proxy_call_sync(agent_manager, "RegisterAgent",
140 #ifdef TIZEN_BT_IO_CAPA_NO_INPUT_OUTPUT
141                         g_variant_new("(os)", priv->path, "NoInputNoOutput"),
142 #else
143                         g_variant_new("(os)", priv->path, "DisplayYesNo"),
144 #endif
145                         G_DBUS_CALL_FLAGS_NONE, -1,
146                         NULL, &error);
147         if (reply == NULL) {
148                 ERR("Agent registration failed");
149                 if (error) {
150                         ERR("Agent registration failed: errCode[%x], message[%s]",
151                                         error->code, error->message);
152
153                         if (error->code == AGENT_ALREADY_EXIST) {
154                                 DBG("Agent is already registered");
155                                 g_clear_error(&error);
156                         } else {
157                                 g_clear_error(&error);
158                                 g_object_unref(agent_manager);
159                                 priv->agent_manager = NULL;
160                                 return FALSE;
161                         }
162                 }
163         }
164         g_variant_unref(reply);
165         reply = NULL;
166
167         /* Set the defalut agent */
168         DBG("agent_manager[%p] priv->path[%s]", agent_manager, priv->path);
169         reply = g_dbus_proxy_call_sync(agent_manager, "RequestDefaultAgent",
170                         g_variant_new("(o)", priv->path),
171                         G_DBUS_CALL_FLAGS_NONE, -1,
172                         NULL, &error);
173         if (reply == NULL) {
174                 ERR("Request Default Agent failed");
175                 if (error) {
176                         ERR("Request Default Agent failed: errCode[%x], message[%s]",
177                                         error->code, error->message);
178                         g_clear_error(&error);
179                 }
180                 g_object_unref(agent_manager);
181                 priv->agent_manager = NULL;
182                 return FALSE;
183         }
184         g_variant_unref(reply);
185
186         priv->agent_manager = agent_manager;
187
188         return TRUE;
189 }
190
191 static const gchar gap_agent_bluez_introspection_xml[] =
192 "<node name='/'>"
193 "  <interface name='org.bluez.Agent1'>"
194 "    <method name='RequestPinCode'>"
195 "      <arg type='o' name='device' direction='in'/>"
196 "      <arg type='s' name='pincode' direction='out'/>"
197 "    </method>"
198 "    <method name='RequestPasskey'>"
199 "      <arg type='o' name='device' direction='in'/>"
200 "      <arg type='u' name='passkey' direction='out'/>"
201 "    </method>"
202 "    <method name='DisplayPasskey'>"
203 "      <arg type='o' name='device' direction='in'/>"
204 "      <arg type='u' name='passkey' direction='in'/>"
205 "      <arg type='q' name='entered' direction='in'/>"
206 "    </method>"
207 "    <method name='RequestConfirmation'>"
208 "      <arg type='o' name='device' direction='in'/>"
209 "      <arg type='u' name='passkey' direction='in'/>"
210 "    </method>"
211 "    <method name='RequestAuthorization'>"
212 "      <arg type='o' name='device' direction='in'/>"
213 "    </method>"
214 "    <method name='AuthorizeService'>"
215 "      <arg type='o' name='device' direction='in'/>"
216 "      <arg type='s' name='uuid' direction='in'/>"
217 "    </method>"
218 "    <method name='Cancel'>"
219 "    </method>"
220 "    <method name='Release'>"
221 "    </method>"
222 "    <method name='ReplyPinCode'>"
223 "      <arg type='u' name='accept' direction='in'/>"
224 "      <arg type='s' name='pincode' direction='in'/>"
225 "    </method>"
226 "    <method name='ReplyPasskey'>"
227 "      <arg type='u' name='accept' direction='in'/>"
228 "      <arg type='s' name='passkey' direction='in'/>"
229 "    </method>"
230 "    <method name='ReplyConfirmation'>"
231 "      <arg type='u' name='accept' direction='in'/>"
232 "    </method>"
233 "    <method name='ReplyAuthorize'>"
234 "      <arg type='u' name='accept' direction='in'/>"
235 "    </method>"
236 "    <method name='ConfirmModeChange'>"
237 "      <arg type='s' name='mode' direction='in'/>"
238 "    </method>"
239 "    <method name='GetDiscoverableTimeout'>"
240 "      <arg type='u' name='timeout' direction='out'/>"
241 "    </method>"
242 "  </interface>"
243 "</node>";
244
245
246 static const GDBusInterfaceVTable method_table = {
247         __bt_gap_agent_method,
248         NULL,
249         NULL,
250 };
251
252 void _gap_agent_setup_dbus(GapAgentPrivate *agent, GAP_AGENT_FUNC_CB *func_cb,
253                 const char *path,
254                 GDBusProxy *adapter)
255 {
256         GapAgentPrivate *priv = agent;
257         GDBusProxy *proxy;
258         GDBusNodeInfo *node_info;
259         GError *error = NULL;
260
261         priv->path = g_strdup(path);
262
263         node_info = __bt_service_create_method_node_info(
264                         gap_agent_bluez_introspection_xml);
265         if (node_info == NULL)
266                 return;
267
268         DBG("path is [%s]", path);
269
270         connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
271         if (!connection) {
272                 if (error) {
273                         ERR("Unable to connect to gdbus: %s", error->message);
274                         g_clear_error(&error);
275                 }
276                 return;
277         }
278
279         if (gap_agent_id == -1) {
280                 gap_agent_id = g_dbus_connection_register_object(connection, path,
281                                 node_info->interfaces[0],
282                                 &method_table, priv,
283                                 NULL, &error);
284         }
285
286         g_dbus_node_info_unref(node_info);
287
288         if (gap_agent_id == 0) {
289                 ERR("Failed to register for Path: %s", path);
290                 if (error) {
291                         ERR("Failed to register: %s", error->message);
292                         g_clear_error(&error);
293                 }
294                 return;
295         }
296
297         memcpy(&priv->cb, func_cb, sizeof(GAP_AGENT_FUNC_CB));
298
299         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
300         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
301         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
302         priv->reply_context = NULL;
303
304         DBG("path: %s", path);
305
306         proxy =  g_dbus_proxy_new_sync(connection,
307                         G_DBUS_PROXY_FLAGS_NONE, NULL,
308                         BT_HAL_BLUEZ_NAME, path,
309                         BT_HAL_AGENT_INTERFACE, NULL, &error);
310
311         if (!proxy) {
312                 ERR("Unable to create proxy");
313                 if (error) {
314                         ERR("Error: %s", error->message);
315                         g_clear_error(&error);
316                 }
317                 priv->busname = NULL;
318         } else {
319                 priv->busname = g_strdup(g_dbus_proxy_get_name(proxy));
320                 g_object_unref(proxy);
321                 DBG("Busname: %s", priv->busname);
322         }
323 }
324
325 void _gap_agent_reset_dbus(GapAgentPrivate *agent)
326 {
327         GapAgentPrivate *priv = agent;
328
329         /* Fix : NULL_RETURNS */
330         if (priv == NULL)
331                 return ;
332
333         __gap_agent_unregister(agent);
334
335         if (gap_agent_id > 0) {
336
337                 if (connection)
338                         g_dbus_connection_unregister_object(connection,
339                                         gap_agent_id);
340                 gap_agent_id = -1;
341         }
342
343 #ifdef TIZEN_BT_HAL
344         if (priv->osp_servers)
345                 __bt_hal_gap_agent_remove_osp_servers(priv->osp_servers);
346 #endif
347
348         g_object_ref(priv->adapter);
349         priv->adapter = NULL;
350
351         g_free(priv->path);
352         priv->path = NULL;
353
354         g_free(priv->busname);
355         priv->busname = NULL;
356 }
357
358 gchar* _gap_agent_get_path(GapAgentPrivate *agent)
359 {
360         GapAgentPrivate *priv = agent;
361
362         /* Fix : NULL_RETURNS */
363         if (priv == NULL)
364                 return NULL;
365
366         return priv->path;
367 }
368
369 gboolean _gap_agent_is_canceled(GapAgentPrivate *agent)
370 {
371         GapAgentPrivate *priv = agent;
372
373         /* Fix : NULL_RETURNS */
374         if (priv == NULL)
375                 return  FALSE;
376
377         return priv->canceled;
378 }
379
380 void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value)
381 {
382         GapAgentPrivate *priv = agent;
383
384         /* Fix : NULL_RETURNS */
385         if (priv == NULL)
386                 return;
387
388         priv->canceled = value;
389 }
390
391 static gboolean __gap_agent_unregister(GapAgentPrivate *agent)
392 {
393         GapAgentPrivate *priv = agent;
394         GDBusProxy *agent_manager;
395         GError *error = NULL;
396         GVariant *reply;
397
398         if (priv == NULL || priv->path == NULL || connection == NULL)
399                 return  FALSE;
400
401         if (priv->agent_manager == NULL) {
402                 agent_manager = g_dbus_proxy_new_sync(connection,
403                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
404                                 BT_HAL_BLUEZ_NAME, BT_HAL_BLUEZ_PATH,
405                                 BT_HAL_AGENT_MANAGER_INTERFACE, NULL, &error);
406                 if (!agent_manager) {
407                         if (error) {
408                                 ERR("Unable to create proxy: %s", error->message);
409                                 g_clear_error(&error);
410                         }
411                         return FALSE;
412                 }
413         } else {
414                 agent_manager = priv->agent_manager;
415         }
416
417         reply = g_dbus_proxy_call_sync(agent_manager, "UnregisterAgent",
418                         g_variant_new("(o)", priv->path),
419                         G_DBUS_CALL_FLAGS_NONE, -1,
420                         NULL, &error);
421         g_object_unref(agent_manager);
422         priv->agent_manager = NULL;
423
424         if (reply == NULL) {
425                 ERR("Agent unregistration failed");
426                 if (error) {
427                         ERR("Agent unregistration failed: errCode[%x], message[%s]",
428                                         error->code, error->message);
429                         g_clear_error(&error);
430                 }
431                 return FALSE;
432         }
433         g_variant_unref(reply);
434
435         return TRUE;
436 }
437
438         static GDBusNodeInfo *__bt_service_create_method_node_info
439 (const gchar *introspection_data)
440 {
441         GError *err = NULL;
442         GDBusNodeInfo *node_info = NULL;
443
444         if (introspection_data == NULL)
445                 return NULL;
446
447         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
448
449         if (err) {
450                 ERR("Unable to create node: %s", err->message);
451                 g_clear_error(&err);
452         }
453         return node_info;
454 }
455
456 static void __bt_gap_agent_method(GDBusConnection *connection,
457                         const gchar *sender,
458                         const gchar *object_path,
459                         const gchar *interface_name,
460                         const gchar *method_name,
461                         GVariant *parameters,
462                         GDBusMethodInvocation *invocation,
463                         gpointer user_data)
464 {
465         FN_START;
466
467         GError *err = NULL;
468         if (g_strcmp0(method_name, "RequestPinCode") == 0) {
469                 GapAgentPrivate *agent = user_data;
470                 GDBusProxy *device;
471                 char *addr;
472                 char *path;
473                 GDBusConnection *conn;
474
475                 if (sender == NULL)
476                         return;
477
478                 g_variant_get(parameters, "(&o)", &path);
479                 INFO("Request pin code, Device Path :%s", path);
480
481                 /* Need to check
482                    if (g_strcmp0(sender, agent->busname) != 0)
483                    return;
484                  */
485
486                 if (!agent->cb.passkey_func)
487                         return;
488                 conn = _bt_hal_get_system_gconn();
489                 if (conn == NULL)
490                         return;
491                 device = g_dbus_proxy_new_sync(conn,
492                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
493                                 BT_HAL_BLUEZ_NAME, path,
494                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
495                 if (!device) {
496                         ERR("Fail to make device proxy");
497                         g_dbus_method_invocation_return_error(invocation,
498                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
499                                         "No proxy for device");
500                         if (err) {
501                                 ERR("Unable to create proxy: %s", err->message);
502                                 g_clear_error(&err);
503                         }
504                         return;
505                 }
506
507                 agent->exec_type = GAP_AGENT_EXEC_PAIRING;
508                 agent->reply_context = invocation;
509
510                 addr = strstr(path, "dev_");
511                 if (addr != NULL) {
512                         char *pos = NULL;
513                         addr += 4;
514                         g_strlcpy(agent->pairing_addr, addr, sizeof(agent->pairing_addr));
515
516                         while ((pos = strchr(agent->pairing_addr, '_')) != NULL)
517                                 *pos = ':';
518                 }
519                 agent->cb.pincode_func(agent, device);
520                 g_object_unref(device);
521                 return;
522         } else if (g_strcmp0(method_name, "RequestPasskey") == 0) {
523                 GapAgentPrivate *priv = user_data;
524                 GDBusProxy *device;
525                 char *addr;
526                 char *path;
527                 GDBusConnection *conn;
528
529                 if (sender == NULL)
530                         return;
531
532                 g_variant_get(parameters, "(&o)", &path);
533                 INFO("Request passkey : sender %s priv->busname %s Device Path :%s",
534                                 sender, priv->busname, path);
535                 /* Need to check
536                    if (g_strcmp0(sender, agent->busname) != 0)
537                    return;
538                  */
539                 if (!priv->cb.passkey_func)
540                         return;
541                 conn = _bt_hal_get_system_gconn();
542                 if (conn == NULL)
543                         return;
544
545                 device = g_dbus_proxy_new_sync(conn,
546                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
547                                 BT_HAL_BLUEZ_NAME, path,
548                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
549
550                 if (!device) {
551                         ERR("Fail to make device proxy");
552
553                         g_dbus_method_invocation_return_error(invocation,
554                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
555                                         "No proxy for device");
556                         if (err) {
557                                 ERR("Unable to create proxy: %s", err->message);
558                                 g_clear_error(&err);
559                         }
560                         return;
561                 }
562                 priv->exec_type = GAP_AGENT_EXEC_PAIRING;
563                 priv->reply_context = invocation;
564
565                 addr = strstr(path, "dev_");
566                 if (addr != NULL) {
567                         char *pos = NULL;
568                         addr += 4;
569                         g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
570
571                         while ((pos = strchr(priv->pairing_addr, '_')) != NULL)
572                                 *pos = ':';
573                 }
574                 priv->cb.passkey_func(priv, device);
575                 g_object_unref(device);
576                 return;
577         } else if (g_strcmp0(method_name, "DisplayPasskey") == 0) {
578                 GapAgentPrivate *priv = user_data;
579                 GDBusProxy *device;
580                 guint passkey;
581                 guint16 entered;
582                 char *path;
583                 GDBusConnection *conn;
584
585                 if (sender == NULL)
586                         return;
587                 g_variant_get(parameters, "(&ouq)", &path, &passkey, &entered);
588                 INFO("Request passkey display :sender %s priv->busname %s"
589                                 " Device Path :%s, Passkey: %d, Entered: %d",
590                                 sender, priv->busname, path, passkey, entered);
591                 /* Do not show popup for Key event while typing*/
592                 if (entered)
593                         return;
594                 /* Need to check
595                    if (g_strcmp0(sender, agent->busname) != 0)
596                    return;
597                  */
598                 if (!priv->cb.display_func)
599                         return;
600
601                 conn = _bt_hal_get_system_gconn();
602                 if (conn == NULL)
603                         return;
604                 device = g_dbus_proxy_new_sync(conn,
605                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
606                                 BT_HAL_BLUEZ_NAME, path,
607                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
608                 if (!device) {
609                         ERR("Fail to make device proxy");
610
611                         g_dbus_method_invocation_return_error(invocation,
612                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
613                                         "No proxy for device");
614                         if (err) {
615                                 ERR("Unable to create proxy: %s", err->message);
616                                 g_clear_error(&err);
617                         }
618                         return;
619                 }
620                 g_dbus_method_invocation_return_value(invocation, NULL);
621                 priv->cb.display_func(priv, device, passkey);
622                 g_object_unref(device);
623                 return;
624         } else if (g_strcmp0(method_name, "RequestConfirmation") == 0) {
625                 GapAgentPrivate *priv = user_data;
626                 GDBusProxy *device;
627                 guint passkey;
628                 char *path;
629                 char *addr;
630                 GDBusConnection *conn;
631
632                 if (sender == NULL)
633                         return;
634
635                 g_variant_get(parameters, "(&ou)", &path, &passkey);
636                 INFO("Request passkey confirmation, Device Path :%s, Passkey: %d",
637                                 path, passkey);
638
639                 DBG("Sender: [%s] priv->busname: [%s]", sender, priv->busname);
640                 /* Need to check
641                    if (g_strcmp0(sender, agent->busname) != 0)
642                    return;
643                  */
644                 DBG("priv->cb.confirm_func [%p]", priv->cb.confirm_func);
645                 if (!priv->cb.confirm_func)
646                         return;
647                 conn = _bt_hal_get_system_gconn();
648                 if (conn == NULL)
649                         return;
650                 device = g_dbus_proxy_new_sync(conn,
651                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
652                                 BT_HAL_BLUEZ_NAME, path,
653                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
654                 if (!device) {
655                         ERR("Fail to make device proxy");
656                         g_dbus_method_invocation_return_error(invocation,
657                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
658                                         "No proxy for device");
659                         if (err) {
660                                 ERR("Unable to create proxy: %s", err->message);
661                                 g_clear_error(&err);
662                         }
663                         return;
664                 }
665                 priv->exec_type = GAP_AGENT_EXEC_PAIRING;
666                 priv->reply_context = invocation;
667                 addr = strstr(path, "dev_");
668                 if (addr != NULL) {
669                         char *pos = NULL;
670                         addr += 4;
671                         g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
672
673                         while ((pos = strchr(priv->pairing_addr, '_')) != NULL)
674                                 *pos = ':';
675                 }
676
677                 DBG("Pairing address [%s]", priv->pairing_addr);
678                 priv->cb.confirm_func(priv, device, passkey);
679                 g_object_unref(device);
680                 return;
681         } else if (g_strcmp0(method_name, "AuthorizeService") == 0) {
682                 GapAgentPrivate *priv = user_data;
683                 GDBusProxy *device;
684                 GDBusConnection *conn;
685                 char *addr;
686                 char *path;
687                 char *uuid;
688
689                 if (sender == NULL)
690                         return;
691
692                 g_variant_get(parameters, "(&o&s)", &path, &uuid);
693                 INFO("Request authorization :sender %s priv->busname %s "
694                                 "Device Path :%s UUID: %s",
695                                 sender, priv->busname, path, uuid);
696
697                 /* Need to check
698                    if (g_strcmp0(sender, agent->busname) != 0)
699                    return;
700                  */
701
702                 if (!priv->cb.authorize_func)
703                         return;
704
705                 conn = _bt_hal_get_system_gconn();
706                 if (conn == NULL)
707                         return;
708
709                 device = g_dbus_proxy_new_sync(conn,
710                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
711                                 BT_HAL_BLUEZ_NAME, path,
712                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
713
714                 if (!device) {
715                         ERR("Fail to make device proxy");
716
717                         g_dbus_method_invocation_return_error(invocation,
718                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
719                                         "No proxy for device");
720
721                         if (err) {
722                                 ERR("Unable to create proxy: %s", err->message);
723                                 g_clear_error(&err);
724                         }
725
726                         return;
727                 }
728
729                 priv->exec_type = GAP_AGENT_EXEC_AUTHORZATION;
730                 priv->reply_context = invocation;
731                 priv->uuid = g_strdup(uuid);
732
733                 addr = strstr(path, "dev_");
734                 if (addr != NULL) {
735                         char *pos = NULL;
736                         addr += 4;
737                         g_strlcpy(priv->authorize_addr, addr,
738                                         sizeof(priv->authorize_addr));
739
740                         while ((pos = strchr(priv->authorize_addr, '_')) != NULL)
741                                 *pos = ':';
742                 }
743
744                 priv->cb.authorize_func(priv, device, uuid);
745
746                 g_object_unref(device);
747                 return;
748         } else if (g_strcmp0(method_name, "RequestAuthorization") == 0) {
749                 if (!TIZEN_PROFILE_WEARABLE) {
750                         /* Accept always */
751                 g_dbus_method_invocation_return_value(invocation, NULL);
752                 } else {
753                         /* TODO: This security feature is applicable for Mobile. */
754                         GapAgentPrivate *priv = user_data;
755                         char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
756                         GDBusProxy *device;
757                         GDBusConnection *conn;
758                         char *addr;
759                         char *path;
760
761                         if (sender == NULL)
762                                 return;
763
764                         g_variant_get(parameters, "(&o)", &path);
765                         DBG("Request authorization :sender %s priv->busname %s"
766                                         "Device Path :%s",
767                                         sender, priv->busname, path);
768
769                         if (!priv->cb.authorize_func)
770                                 return;
771
772                         conn = _bt_hal_get_system_gconn();
773                         if (conn == NULL)
774                                 return;
775
776                         device = g_dbus_proxy_new_sync(conn,
777                                         G_DBUS_PROXY_FLAGS_NONE, NULL,
778                                         BT_HAL_BLUEZ_NAME, path,
779                                         BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
780
781                         if (!device) {
782                                 ERR("Fail to make device proxy");
783
784                                 g_dbus_method_invocation_return_error(invocation,
785                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
786                                                 "No proxy for device");
787
788                                 if (err) {
789                                         ERR("Unable to create proxy: %s", err->message);
790                                         g_clear_error(&err);
791                                 }
792
793                                 return;
794                         }
795
796                         priv->exec_type = GAP_AGENT_EXEC_AUTHORZATION;
797                         priv->reply_context = invocation;
798
799                         addr = strstr(path, "dev_");
800                         if (addr != NULL) {
801                                 char *pos = NULL;
802                                 addr += 4;
803                                 g_strlcpy(priv->authorize_addr, addr,
804                                                                 sizeof(priv->authorize_addr));
805
806                                 while ((pos = strchr(priv->authorize_addr, '_')) != NULL)
807                                         *pos = ':';
808                         }
809
810                         priv->cb.authorize_func(priv, device, GAP_UUID);
811
812                         g_object_unref(device);
813                         return;
814                 }
815         } else if (g_strcmp0(method_name, "ConfirmModeChange") == 0) {
816                 g_dbus_method_invocation_return_value(invocation, NULL);
817         } else if (g_strcmp0(method_name, "Cancel") == 0) {
818                 GapAgentPrivate *priv = user_data;
819
820                 if (sender == NULL)
821                         return;
822                 INFO("Cancelled : agent %p sender %p", priv, sender);
823                 /* Need to check
824                    if (g_strcmp0(sender, agent->busname) != 0)
825                    return;
826                  */
827                 if (priv->cb.authorization_cancel_func &&
828                                 priv->exec_type == GAP_AGENT_EXEC_AUTHORZATION) {
829                         DBG("Call GAP agent cancel Authorization method.");
830                         priv->cb.authorization_cancel_func(priv,
831                                         priv->authorize_addr);
832                         memset(priv->authorize_addr, 0x00,
833                                         sizeof(priv->authorize_addr));
834                 } else if (priv->cb.pairing_cancel_func &&
835                                 priv->exec_type == GAP_AGENT_EXEC_PAIRING) {
836                         DBG("Call GAP agent cancel Pairing method.");
837                         priv->cb.pairing_cancel_func(priv,
838                                         priv->pairing_addr);
839                         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
840                 }
841                 if (priv->exec_type != GAP_AGENT_EXEC_CONFIRM_MODE &&
842                                 priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
843                                 priv->reply_context != NULL) {
844
845                         g_dbus_method_invocation_return_error(priv->reply_context,
846                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
847                                         "Rejected by remote cancel");
848                 }
849
850                 /* Canceled flag is set when user cancels pairing request
851                  * Since here bluez has cancelled pairing request, we set the flag to false
852                  */
853                 priv->canceled = FALSE;
854                 priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
855                 priv->reply_context = NULL;
856                 return;
857         } else if (g_strcmp0(method_name, "Release") == 0) {
858                 GapAgentPrivate *priv = user_data;
859
860                 if (sender == NULL)
861                         return;
862
863                 INFO("Released : sender %s\n", sender);
864
865                 /* Need to check
866                 if (g_strcmp0(sender, agent->busname) != 0)
867                         return;
868                  */
869
870                 g_dbus_method_invocation_return_value(invocation, NULL);
871
872                 if (priv) {
873                         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
874                         priv->reply_context = NULL;
875
876                         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
877                         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
878                 }
879                 return;
880         } else if (g_strcmp0(method_name, "GetDiscoverableTimeout") == 0) {
881                 /* TODO */
882         } else if (g_strcmp0(method_name, "ReplyPinCode") == 0) {
883                 GapAgentPrivate *priv = user_data;
884                 const char *pin_code;
885                 guint accept;
886
887                 g_variant_get(parameters, "(u&s)", &accept, &pin_code);
888                 INFO("Accept: %d PinCode: %s", accept, pin_code);
889                 gap_agent_reply_pin_code(priv, accept, pin_code, invocation);
890         } else if (g_strcmp0(method_name, "ReplyPasskey") == 0) {
891                 GapAgentPrivate *priv = user_data;
892                 const char *passkey;
893                 guint accept;
894
895                 g_variant_get(parameters, "(u&s)", &accept, &passkey);
896                 INFO("Accept: %d PinCode: %s", accept, passkey);
897                 gap_agent_reply_passkey(priv, accept, passkey, invocation);
898         } else if (g_strcmp0(method_name, "ReplyConfirmation") == 0) {
899                 GapAgentPrivate *priv = user_data;
900                 guint accept;
901
902                 g_variant_get(parameters, "(u)", &accept);
903                 INFO("Accept: %d", accept);
904                 gap_agent_reply_confirmation(priv, accept, invocation);
905         } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
906                 GapAgentPrivate *priv = user_data;
907                 guint accept;
908
909                 g_variant_get(parameters, "(u)", &accept);
910                 INFO("Accept: %d", accept);
911                 gap_agent_reply_authorize(priv, accept, invocation);
912         } else {
913                 ERR("Invalid method[%s] Object Path[%s] Interface Name[%s]",
914                         method_name, object_path, interface_name);
915         }
916 }
917
918 gboolean gap_agent_reply_confirmation(GapAgentPrivate *agent, const guint accept,
919                 GDBusMethodInvocation *context)
920 {
921         GapAgentPrivate *priv = agent;
922
923         /* Fix : NULL_RETURNS */
924         if (priv == NULL)
925                 return FALSE;
926
927         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
928                         priv->reply_context != NULL) {
929                 if (accept == GAP_AGENT_ACCEPT || accept == GAP_AGENT_ACCEPT_ALWAYS) {
930                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
931                         priv->canceled = FALSE;
932                 } else {
933                         switch (accept) {
934                         case GAP_AGENT_CANCEL:
935                                 g_dbus_method_invocation_return_error(priv->reply_context,
936                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
937                                                 "CanceledbyUser");
938                                 priv->canceled = TRUE;
939                                 break;
940                         case GAP_AGENT_TIMEOUT:
941                         case GAP_AGENT_REJECT:
942                         default:
943                                 g_dbus_method_invocation_return_error(priv->reply_context,
944                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
945                                                 "Confirmation request rejected");
946                                 priv->canceled = FALSE;
947                                 break;
948                         }
949                 }
950         }
951
952         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
953         priv->reply_context = NULL;
954         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
955
956         return TRUE;
957 }
958
959 gboolean gap_agent_reply_pin_code(GapAgentPrivate *agent, const guint accept,
960                 const char *pin_code,
961                 GDBusMethodInvocation *context)
962 {
963         GapAgentPrivate *priv = agent;
964
965         /* Fix : NULL_RETURNS */
966         if (priv == NULL)
967                 return FALSE;
968
969         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
970                         priv->reply_context != NULL) {
971                 if (accept == GAP_AGENT_ACCEPT) {
972                         g_dbus_method_invocation_return_value(priv->reply_context,
973                                         g_variant_new("(s)", pin_code));
974                         priv->canceled = FALSE;
975                 } else {
976                         switch (accept) {
977                         case GAP_AGENT_CANCEL:
978                                 g_dbus_method_invocation_return_error(priv->reply_context,
979                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
980                                                 "CanceledbyUser");
981                                 priv->canceled = TRUE;
982                                 break;
983                         case GAP_AGENT_TIMEOUT:
984                         case GAP_AGENT_REJECT:
985                         default:
986                                 g_dbus_method_invocation_return_error(priv->reply_context,
987                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
988                                                 "Pairing request rejected");
989                                 priv->canceled = FALSE;
990                                 break;
991                         }
992                 }
993         }
994         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
995         priv->reply_context = NULL;
996         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
997
998         return TRUE;
999 }
1000
1001 gboolean gap_agent_reply_passkey(GapAgentPrivate *agent, const guint accept,
1002                 const char *passkey,
1003                 GDBusMethodInvocation *context)
1004 {
1005         GapAgentPrivate *priv = agent;
1006
1007         /* Fix : NULL_RETURNS */
1008         if (priv == NULL)
1009                 return FALSE;
1010
1011         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
1012                         priv->reply_context != NULL) {
1013                 if (accept == GAP_AGENT_ACCEPT) {
1014                         guint pass_key = atoi(passkey);
1015                         g_dbus_method_invocation_return_value(priv->reply_context,
1016                                         g_variant_new("(u)", pass_key));
1017                         priv->canceled = FALSE;
1018                 } else {
1019                         switch (accept) {
1020                         case GAP_AGENT_CANCEL:
1021                                 g_dbus_method_invocation_return_error(priv->reply_context,
1022                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
1023                                                 "CanceledbyUser");
1024                                 priv->canceled = TRUE;
1025                                 break;
1026                         case GAP_AGENT_TIMEOUT:
1027                         case GAP_AGENT_REJECT:
1028                         default:
1029                                 g_dbus_method_invocation_return_error(priv->reply_context,
1030                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
1031                                                 "Passkey request rejected");
1032                                 priv->canceled = FALSE;
1033                                 break;
1034                         }
1035                 }
1036         }
1037
1038         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
1039         priv->reply_context = NULL;
1040         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
1041
1042         return TRUE;
1043 }
1044
1045 gboolean gap_agent_reply_authorize(GapAgentPrivate *agent, const guint accept,
1046                 GDBusMethodInvocation *context)
1047 {
1048         gboolean ret = TRUE;
1049         GapAgentPrivate *priv = agent;
1050
1051         /* Fix : NULL_RETURNS */
1052         if (priv == NULL)
1053                 return  FALSE;
1054
1055         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
1056                         priv->reply_context != NULL) {
1057                 if (accept == GAP_AGENT_ACCEPT) {
1058                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
1059                 } else if (accept == GAP_AGENT_ACCEPT_ALWAYS) {
1060                         bluetooth_device_address_t addr = { { 0, } };
1061                         int result;
1062                         bt_trusted_profile_t profile;
1063
1064                         _bt_hal_convert_addr_string_to_type(addr.addr,
1065                                                         priv->authorize_addr);
1066
1067                         profile = _bt_hal_get_trusted_profile_enum(priv->uuid);
1068
1069                         if (profile)
1070                                 result = _bt_hal_device_set_trusted_profile((bt_bdaddr_t *)(&addr), profile, TRUE);
1071                         else
1072                                 result = _bt_hal_device_set_trust((bt_bdaddr_t *)(&addr), TRUE);
1073
1074                         if (result == BT_STATUS_SUCCESS) {
1075                                 INFO("[%s] Profile added as trusted for Device[%s]",
1076                                                 priv->uuid, priv->authorize_addr);
1077                         }
1078
1079                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
1080                 } else {
1081                         switch (accept) {
1082                         case GAP_AGENT_CANCEL:
1083                                 g_dbus_method_invocation_return_error(priv->reply_context,
1084                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
1085                                                 "CanceledbyUser");
1086                                 break;
1087                         case GAP_AGENT_TIMEOUT:
1088                         case GAP_AGENT_REJECT:
1089                         default:
1090                                 g_dbus_method_invocation_return_error(priv->reply_context,
1091                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
1092                                                 "Authorization request rejected");
1093                                 break;
1094                         }
1095                 }
1096
1097                 if (context)
1098                         g_dbus_method_invocation_return_value(context, NULL);
1099         } else {
1100                 ERR("No context");
1101                 if (context)
1102                         g_dbus_method_invocation_return_error(context,
1103                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
1104                                         "No context");
1105                 ret = FALSE;
1106         }
1107
1108         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
1109         priv->reply_context = NULL;
1110         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
1111
1112         if (priv->uuid) {
1113                 g_free(priv->uuid);
1114                 priv->uuid = NULL;
1115         }
1116         return ret;
1117 }
1118
1119 #ifdef TIZEN_BT_HAL
1120 bt_hal_agent_osp_server_t *_bt_hal_gap_agent_find_osp_server_by_type(GSList *servers, unsigned int type, const char *uuid)
1121 {
1122         GSList *l;
1123         bt_hal_agent_osp_server_t *server;
1124
1125         for (l = servers; l != NULL; l = g_slist_next(l)) {
1126                 server = l->data;
1127
1128                 if (server == NULL)
1129                         continue;
1130
1131                 /* No uuid in obex server */
1132                 if (type == BT_OSP_SERVER_OBEX
1133                                 && server->type == BT_OSP_SERVER_OBEX)
1134                         return server;
1135
1136                 if (g_strcmp0(server->uuid, uuid) == 0)
1137                         return server;
1138         }
1139
1140         return NULL;
1141 }
1142
1143 gboolean _bt_hal_gap_agent_register_osp_server(GapAgentPrivate *agent, unsigned int type, char *uuid, char *path, int fd)
1144 {
1145         bt_hal_agent_osp_server_t *server;
1146
1147         GapAgentPrivate *priv = agent;
1148         if (priv == NULL)
1149                 return FALSE;
1150
1151         if (type >= BT_OSP_SERVER_MAX)
1152                 return FALSE;
1153
1154         server = g_malloc0(sizeof(bt_hal_agent_osp_server_t));
1155         server->type = type;
1156         if (type == BT_OSP_SERVER_RFCOMM && uuid && path) {
1157                 server->uuid = g_strdup(uuid);
1158                 server->path = g_strdup(path);
1159                 server->fd = fd;
1160         }
1161         priv->osp_servers = g_slist_append(priv->osp_servers, server);
1162
1163         return TRUE;
1164 }
1165
1166 gboolean _bt_hal_gap_agent_unregister_osp_server(GapAgentPrivate *agent, unsigned int type, char *uuid)
1167 {
1168         bt_hal_agent_osp_server_t *server;
1169
1170         GapAgentPrivate *priv = agent;
1171
1172         if (priv == NULL)
1173                 return FALSE;
1174
1175         if (type >= BT_OSP_SERVER_MAX)
1176                 return FALSE;
1177
1178         server = _bt_hal_gap_agent_find_osp_server_by_type(priv->osp_servers, type, uuid);
1179         if (server == NULL)
1180                 return TRUE;
1181
1182         priv->osp_servers = g_slist_remove(priv->osp_servers, server);
1183         __bt_hal_free_osp_server(server);
1184
1185         return TRUE;
1186 }
1187 #endif