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