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