Fix dlog format error
[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                 GDBusProxy *device;
472                 char *addr;
473                 char *path;
474                 GDBusConnection *conn;
475
476                 if (sender == NULL)
477                         return;
478
479                 g_variant_get(parameters, "(&o)", &path);
480                 DBG("Request pin code, Device Path :%s", path);
481
482                 /* Need to check
483                    if (g_strcmp0(sender, agent->busname) != 0)
484                    return;
485                  */
486
487                 if (!agent->cb.passkey_func)
488                         return;
489                 conn = _bt_hal_get_system_gconn();
490                 if (conn == NULL)
491                         return;
492                 device = g_dbus_proxy_new_sync(conn,
493                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
494                                 BT_HAL_BLUEZ_NAME, path,
495                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
496                 if (!device) {
497                         ERR("Fail to make device proxy");
498                         g_dbus_method_invocation_return_error(invocation,
499                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
500                                         "No proxy for device");
501                         if (err) {
502                                 ERR("Unable to create proxy: %s", err->message);
503                                 g_clear_error(&err);
504                         }
505                         return;
506                 }
507
508                 agent->exec_type = GAP_AGENT_EXEC_PAIRING;
509                 agent->reply_context = invocation;
510
511                 addr = strstr(path, "dev_");
512                 if (addr != NULL) {
513                         char *pos = NULL;
514                         addr += 4;
515                         g_strlcpy(agent->pairing_addr, addr, sizeof(agent->pairing_addr));
516
517                         while ((pos = strchr(agent->pairing_addr, '_')) != NULL)
518                                 *pos = ':';
519                 }
520                 agent->cb.pincode_func(agent, device);
521                 g_object_unref(device);
522                 return;
523         } else if (g_strcmp0(method_name, "RequestPasskey") == 0) {
524                 GapAgentPrivate *priv = user_data;
525                 GDBusProxy *device;
526                 char *addr;
527                 char *path;
528                 GDBusConnection *conn;
529
530                 if (sender == NULL)
531                         return;
532
533                 g_variant_get(parameters, "(&o)", &path);
534                 DBG("Request passkey : sender %s priv->busname %s Device Path :%s",
535                                 sender, priv->busname, path);
536                 /* Need to check
537                    if (g_strcmp0(sender, agent->busname) != 0)
538                    return;
539                  */
540                 if (!priv->cb.passkey_func)
541                         return;
542                 conn = _bt_hal_get_system_gconn();
543                 if (conn == NULL)
544                         return;
545
546                 device = g_dbus_proxy_new_sync(conn,
547                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
548                                 BT_HAL_BLUEZ_NAME, path,
549                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
550
551                 if (!device) {
552                         ERR("Fail to make device proxy");
553
554                         g_dbus_method_invocation_return_error(invocation,
555                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
556                                         "No proxy for device");
557                         if (err) {
558                                 ERR("Unable to create proxy: %s", err->message);
559                                 g_clear_error(&err);
560                         }
561                         return;
562                 }
563                 priv->exec_type = GAP_AGENT_EXEC_PAIRING;
564                 priv->reply_context = invocation;
565
566                 addr = strstr(path, "dev_");
567                 if (addr != NULL) {
568                         char *pos = NULL;
569                         addr += 4;
570                         g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
571
572                         while ((pos = strchr(priv->pairing_addr, '_')) != NULL)
573                                 *pos = ':';
574                 }
575                 priv->cb.passkey_func(priv, device);
576                 g_object_unref(device);
577                 return;
578         } else if (g_strcmp0(method_name, "DisplayPasskey") == 0) {
579                 GapAgentPrivate *priv = user_data;
580                 GDBusProxy *device;
581                 guint passkey;
582                 guint16 entered;
583                 char *path;
584                 GDBusConnection *conn;
585
586                 if (sender == NULL)
587                         return;
588                 g_variant_get(parameters, "(&ouq)", &path, &passkey, &entered);
589                 DBG("Request passkey display :sender %s priv->busname %s"
590                                 " Device Path :%s, Passkey: %d, Entered: %d",
591                                 sender, priv->busname, path, passkey, entered);
592                 /* Do not show popup for Key event while typing*/
593                 if (entered)
594                         return;
595                 /* Need to check
596                    if (g_strcmp0(sender, agent->busname) != 0)
597                    return;
598                  */
599                 if (!priv->cb.display_func)
600                         return;
601
602                 conn = _bt_hal_get_system_gconn();
603                 if (conn == NULL)
604                         return;
605                 device = g_dbus_proxy_new_sync(conn,
606                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
607                                 BT_HAL_BLUEZ_NAME, path,
608                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
609                 if (!device) {
610                         ERR("Fail to make device proxy");
611
612                         g_dbus_method_invocation_return_error(invocation,
613                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
614                                         "No proxy for device");
615                         if (err) {
616                                 ERR("Unable to create proxy: %s", err->message);
617                                 g_clear_error(&err);
618                         }
619                         return;
620                 }
621                 g_dbus_method_invocation_return_value(invocation, NULL);
622                 priv->cb.display_func(priv, device, passkey);
623                 g_object_unref(device);
624                 return;
625         } else if (g_strcmp0(method_name, "RequestConfirmation") == 0) {
626                 GapAgentPrivate *priv = user_data;
627                 GDBusProxy *device;
628                 guint passkey;
629                 char *path;
630                 char *addr;
631                 GDBusConnection *conn;
632
633                 if (sender == NULL)
634                         return;
635
636                 g_variant_get(parameters, "(&ou)", &path, &passkey);
637                 DBG("Request passkey confirmation, Device Path :%s, Passkey: %d",
638                                 path, passkey);
639
640                 DBG("Sender: [%s] priv->busname: [%s]", sender, priv->busname);
641                 /* Need to check
642                    if (g_strcmp0(sender, agent->busname) != 0)
643                    return;
644                  */
645                 DBG("priv->cb.confirm_func [%p]", priv->cb.confirm_func);
646                 if (!priv->cb.confirm_func)
647                         return;
648                 conn = _bt_hal_get_system_gconn();
649                 if (conn == NULL)
650                         return;
651                 device = g_dbus_proxy_new_sync(conn,
652                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
653                                 BT_HAL_BLUEZ_NAME, path,
654                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
655                 if (!device) {
656                         ERR("Fail to make device proxy");
657                         g_dbus_method_invocation_return_error(invocation,
658                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
659                                         "No proxy for device");
660                         if (err) {
661                                 ERR("Unable to create proxy: %s", err->message);
662                                 g_clear_error(&err);
663                         }
664                         return;
665                 }
666                 priv->exec_type = GAP_AGENT_EXEC_PAIRING;
667                 priv->reply_context = invocation;
668                 addr = strstr(path, "dev_");
669                 if (addr != NULL) {
670                         char *pos = NULL;
671                         addr += 4;
672                         g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
673
674                         while ((pos = strchr(priv->pairing_addr, '_')) != NULL)
675                                 *pos = ':';
676                 }
677
678                 DBG("Pairing address [%s]", priv->pairing_addr);
679                 priv->cb.confirm_func(priv, device, passkey);
680                 g_object_unref(device);
681                 return;
682         } else if (g_strcmp0(method_name, "AuthorizeService") == 0) {
683                 GapAgentPrivate *priv = user_data;
684                 GDBusProxy *device;
685                 GDBusConnection *conn;
686                 char *addr;
687                 char *path;
688                 char *uuid;
689
690                 if (sender == NULL)
691                         return;
692
693                 g_variant_get(parameters, "(&o&s)", &path, &uuid);
694                 DBG("Request authorization :sender %s priv->busname %s "
695                                 "Device Path :%s UUID: %s",
696                                 sender, priv->busname, path, uuid);
697
698                 /* Need to check
699                    if (g_strcmp0(sender, agent->busname) != 0)
700                    return;
701                  */
702
703                 if (!priv->cb.authorize_func)
704                         return;
705
706                 conn = _bt_hal_get_system_gconn();
707                 if (conn == NULL)
708                         return;
709
710                 device = g_dbus_proxy_new_sync(conn,
711                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
712                                 BT_HAL_BLUEZ_NAME, path,
713                                 BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
714
715                 if (!device) {
716                         ERR("Fail to make device proxy");
717
718                         g_dbus_method_invocation_return_error(invocation,
719                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
720                                         "No proxy for device");
721
722                         if (err) {
723                                 ERR("Unable to create proxy: %s", err->message);
724                                 g_clear_error(&err);
725                         }
726
727                         return;
728                 }
729
730                 priv->exec_type = GAP_AGENT_EXEC_AUTHORZATION;
731                 priv->reply_context = invocation;
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                 g_dbus_method_invocation_return_value(invocation, NULL);
750         } else if (g_strcmp0(method_name, "ConfirmModeChange") == 0) {
751                 g_dbus_method_invocation_return_value(invocation, NULL);
752         } else if (g_strcmp0(method_name, "Cancel") == 0) {
753                 GapAgentPrivate *priv = user_data;
754
755                 if (sender == NULL)
756                         return;
757                 DBG("Cancelled : agent %p sender %p", priv, sender);
758                 /* Need to check
759                    if (g_strcmp0(sender, agent->busname) != 0)
760                    return;
761                  */
762                 if (priv->cb.authorization_cancel_func &&
763                                 priv->exec_type == GAP_AGENT_EXEC_AUTHORZATION) {
764                         DBG("Call GAP agent cancel Authorization method.");
765                         priv->cb.authorization_cancel_func(priv,
766                                         priv->authorize_addr);
767                         memset(priv->authorize_addr, 0x00,
768                                         sizeof(priv->authorize_addr));
769                 } else if (priv->cb.pairing_cancel_func &&
770                                 priv->exec_type == GAP_AGENT_EXEC_PAIRING) {
771                         DBG("Call GAP agent cancel Pairing method.");
772                         priv->cb.pairing_cancel_func(priv,
773                                         priv->pairing_addr);
774                         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
775                 }
776                 if (priv->exec_type != GAP_AGENT_EXEC_CONFIRM_MODE &&
777                                 priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
778                                 priv->reply_context != NULL) {
779
780                         g_dbus_method_invocation_return_error(priv->reply_context,
781                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
782                                         "Rejected by remote cancel");
783                 }
784
785                 /* Canceled flag is set when user cancels pairing request
786                  * Since here bluez has cancelled pairing request, we set the flag to false
787                  */
788                 priv->canceled = FALSE;
789                 priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
790                 priv->reply_context = NULL;
791                 return;
792         } else if (g_strcmp0(method_name, "Release") == 0) {
793                 GapAgentPrivate *priv = user_data;
794
795                 if (sender == NULL)
796                         return;
797
798                 DBG("Released : sender %s\n", sender);
799
800                 /* Need to check
801                 if (g_strcmp0(sender, agent->busname) != 0)
802                         return;
803                  */
804
805                 g_dbus_method_invocation_return_value(invocation, NULL);
806
807                 if (priv) {
808                         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
809                         priv->reply_context = NULL;
810
811                         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
812                         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
813                 }
814                 return;
815         } else if (g_strcmp0(method_name, "GetDiscoverableTimeout") == 0) {
816                 /* TODO */
817         } else if (g_strcmp0(method_name, "ReplyPinCode") == 0) {
818                 GapAgentPrivate *priv = user_data;
819                 const char *pin_code;
820                 guint accept;
821
822                 g_variant_get(parameters, "(u&s)", &accept, &pin_code);
823                 DBG("Accept: %d PinCode: %s", accept, pin_code);
824                 gap_agent_reply_pin_code(priv, accept, pin_code, invocation);
825         } else if (g_strcmp0(method_name, "ReplyPasskey") == 0) {
826                 GapAgentPrivate *priv = user_data;
827                 const char *passkey;
828                 guint accept;
829
830                 g_variant_get(parameters, "(u&s)", &accept, &passkey);
831                 DBG("Accept: %d PinCode: %s", accept, passkey);
832                 gap_agent_reply_passkey(priv, accept, passkey, invocation);
833         } else if (g_strcmp0(method_name, "ReplyConfirmation") == 0) {
834                 GapAgentPrivate *priv = user_data;
835                 guint accept;
836
837                 g_variant_get(parameters, "(u)", &accept);
838                 DBG("Accept: %d", accept);
839                 gap_agent_reply_confirmation(priv, accept, invocation);
840         } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
841                 GapAgentPrivate *priv = user_data;
842                 guint accept;
843
844                 g_variant_get(parameters, "(u)", &accept);
845                 DBG("Accept: %d", accept);
846                 gap_agent_reply_authorize(priv, accept, invocation);
847         }
848         DBG("-");
849 }
850
851 gboolean gap_agent_reply_confirmation(GapAgentPrivate *agent, const guint accept,
852                 GDBusMethodInvocation *context)
853 {
854
855         DBG("+");
856
857         GapAgentPrivate *priv = agent;
858
859         /* Fix : NULL_RETURNS */
860         if (priv == NULL)
861                 return FALSE;
862
863         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
864                         priv->reply_context != NULL) {
865                 if (accept == GAP_AGENT_ACCEPT || accept == GAP_AGENT_ACCEPT_ALWAYS) {
866                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
867                         priv->canceled = FALSE;
868                 } else {
869                         switch (accept) {
870                         case GAP_AGENT_CANCEL:
871                                 g_dbus_method_invocation_return_error(priv->reply_context,
872                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
873                                                 "CanceledbyUser");
874                                 priv->canceled = TRUE;
875                                 break;
876                         case GAP_AGENT_TIMEOUT:
877                         case GAP_AGENT_REJECT:
878                         default:
879                                 g_dbus_method_invocation_return_error(priv->reply_context,
880                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
881                                                 "Confirmation request rejected");
882                                 priv->canceled = FALSE;
883                                 break;
884                         }
885                 }
886         }
887
888         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
889         priv->reply_context = NULL;
890         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
891
892         DBG("-");
893         return TRUE;
894 }
895
896 gboolean gap_agent_reply_pin_code(GapAgentPrivate *agent, const guint accept,
897                 const char *pin_code,
898                 GDBusMethodInvocation *context)
899 {
900         DBG("+");
901         GapAgentPrivate *priv = agent;
902
903         /* Fix : NULL_RETURNS */
904         if (priv == NULL)
905                 return FALSE;
906
907         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
908                         priv->reply_context != NULL) {
909                 if (accept == GAP_AGENT_ACCEPT) {
910                         g_dbus_method_invocation_return_value(priv->reply_context,
911                                         g_variant_new("(s)", pin_code));
912                         priv->canceled = FALSE;
913                 } else {
914                         switch (accept) {
915                         case GAP_AGENT_CANCEL:
916                                 g_dbus_method_invocation_return_error(priv->reply_context,
917                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
918                                                 "CanceledbyUser");
919                                 priv->canceled = TRUE;
920                                 break;
921                         case GAP_AGENT_TIMEOUT:
922                         case GAP_AGENT_REJECT:
923                         default:
924                                 g_dbus_method_invocation_return_error(priv->reply_context,
925                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
926                                                 "Pairing request rejected");
927                                 priv->canceled = FALSE;
928                                 break;
929                         }
930                 }
931         }
932         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
933         priv->reply_context = NULL;
934         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
935
936         DBG("-");
937         return TRUE;
938 }
939
940 gboolean gap_agent_reply_passkey(GapAgentPrivate *agent, const guint accept,
941                 const char *passkey,
942                 GDBusMethodInvocation *context)
943 {
944         DBG("+");
945         GapAgentPrivate *priv = agent;
946
947         /* Fix : NULL_RETURNS */
948         if (priv == NULL)
949                 return FALSE;
950
951         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
952                         priv->reply_context != NULL) {
953                 if (accept == GAP_AGENT_ACCEPT) {
954                         guint pass_key = atoi(passkey);
955                         g_dbus_method_invocation_return_value(priv->reply_context,
956                                         g_variant_new("(u)", pass_key));
957                         priv->canceled = FALSE;
958                 } else {
959                         switch (accept) {
960                         case GAP_AGENT_CANCEL:
961                                 g_dbus_method_invocation_return_error(priv->reply_context,
962                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
963                                                 "CanceledbyUser");
964                                 priv->canceled = TRUE;
965                                 break;
966                         case GAP_AGENT_TIMEOUT:
967                         case GAP_AGENT_REJECT:
968                         default:
969                                 g_dbus_method_invocation_return_error(priv->reply_context,
970                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
971                                                 "Passkey request rejected");
972                                 priv->canceled = FALSE;
973                                 break;
974                         }
975                 }
976         }
977
978         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
979         priv->reply_context = NULL;
980         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
981
982         DBG("-");
983         return TRUE;
984 }
985
986 gboolean gap_agent_reply_authorize(GapAgentPrivate *agent, const guint accept,
987                 GDBusMethodInvocation *context)
988 {
989         gboolean ret = TRUE;
990         GapAgentPrivate *priv = agent;
991         DBG("+");
992
993         /* Fix : NULL_RETURNS */
994         if (priv == NULL)
995                 return  FALSE;
996
997         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
998                         priv->reply_context != NULL) {
999                 if (accept == GAP_AGENT_ACCEPT) {
1000                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
1001                 } else if (accept == GAP_AGENT_ACCEPT_ALWAYS) {
1002                         /* TODO: Enable below logic after set authorization API implementation */
1003                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
1004                 } else {
1005                         switch (accept) {
1006                         case GAP_AGENT_CANCEL:
1007                                 g_dbus_method_invocation_return_error(priv->reply_context,
1008                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
1009                                                 "CanceledbyUser");
1010                                 break;
1011                         case GAP_AGENT_TIMEOUT:
1012                         case GAP_AGENT_REJECT:
1013                         default:
1014                                 g_dbus_method_invocation_return_error(priv->reply_context,
1015                                                 GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
1016                                                 "Authorization request rejected");
1017                                 break;
1018                         }
1019                 }
1020
1021                 if (context)
1022                         g_dbus_method_invocation_return_value(context, NULL);
1023         } else {
1024                 ERR("No context");
1025                 if (context)
1026                         g_dbus_method_invocation_return_error(context,
1027                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
1028                                         "No context");
1029                 ret = FALSE;
1030         }
1031
1032         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
1033         priv->reply_context = NULL;
1034         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
1035
1036         DBG("-");
1037         return ret;
1038 }
1039
1040 #ifdef TIZEN_BT_HAL
1041 bt_hal_agent_osp_server_t *_bt_hal_gap_agent_find_osp_server_by_type(GSList *servers, unsigned int type)
1042 {
1043         GSList *l;
1044         bt_hal_agent_osp_server_t *server;
1045
1046         for (l = servers; l != NULL; l = g_slist_next(l)) {
1047                 server = l->data;
1048
1049                 if (server == NULL)
1050                         continue;
1051
1052                 if (type == server->type)
1053                         return server;
1054         }
1055
1056         return NULL;
1057 }
1058
1059 gboolean _bt_hal_gap_agent_register_osp_server(GapAgentPrivate *agent, unsigned int type)
1060 {
1061         bt_hal_agent_osp_server_t *server;
1062
1063         DBG("+");
1064
1065         GapAgentPrivate *priv = agent;
1066         if (priv == NULL)
1067                 return FALSE;
1068
1069         if (type >= BT_OSP_SERVER_MAX)
1070                 return FALSE;
1071
1072         server = g_malloc0(sizeof(bt_hal_agent_osp_server_t));
1073         server->type = type;
1074         priv->osp_servers = g_slist_append(priv->osp_servers, server);
1075
1076         DBG("-");
1077         return TRUE;
1078 }
1079
1080 gboolean _bt_hal_gap_agent_unregister_osp_server(GapAgentPrivate *agent, unsigned int type)
1081 {
1082         bt_hal_agent_osp_server_t *server;
1083
1084         GapAgentPrivate *priv = agent;
1085
1086         DBG("+");
1087         if (priv == NULL)
1088                 return FALSE;
1089
1090         if (type >= BT_OSP_SERVER_MAX)
1091                 return FALSE;
1092
1093         server = _bt_hal_gap_agent_find_osp_server_by_type(priv->osp_servers, type);
1094         if (server == NULL)
1095                 return TRUE;
1096
1097         priv->osp_servers = g_slist_remove(priv->osp_servers, server);
1098         __bt_hal_free_osp_server(server);
1099
1100         DBG("-");
1101         return TRUE;
1102 }
1103 #endif