[Adapt: HAL] Add support for 'Authorize Cancel' request from Remote
[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                         DBG("Call GAP agent cancel Authorization method.");
749                         priv->cb.authorization_cancel_func(priv,
750                                         priv->authorize_addr);
751                         memset(priv->authorize_addr, 0x00,
752                                         sizeof(priv->authorize_addr));
753                 } else if (priv->cb.pairing_cancel_func &&
754                                 priv->exec_type == GAP_AGENT_EXEC_PAIRING) {
755                         priv->cb.pairing_cancel_func(priv,
756                                         priv->pairing_addr);
757                         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
758                 }
759                 if (priv->exec_type != GAP_AGENT_EXEC_CONFIRM_MODE &&
760                                 priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
761                                 priv->reply_context != NULL) {
762
763                         g_dbus_method_invocation_return_error(priv->reply_context,
764                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
765                                         "Rejected by remote cancel");
766                 }
767
768                 /* Canceled flag is set when user cancels pairing request
769                  * Since here bluez has cancelled pairing request, we set the flag to false
770                  */
771                 priv->canceled = FALSE;
772                 priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
773                 priv->reply_context = NULL;
774                 return;
775         } else if (g_strcmp0(method_name, "Release") == 0) {
776                 GapAgentPrivate *priv = user_data;
777                 char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
778
779                 if (sender == NULL)
780                         return;
781
782                 DBG("Released : sender %s\n", sender);
783
784                 /* Need to check
785                 if (g_strcmp0(sender, agent->busname) != 0)
786                         return;
787                  */
788
789                 g_dbus_method_invocation_return_value(invocation, NULL);
790
791                 if (priv) {
792                         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
793                         priv->reply_context = NULL;
794
795                         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
796                         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
797                 }
798                 return;
799         } else if (g_strcmp0(method_name, "GetDiscoverableTimeout") == 0) {
800                 /* TODO */
801         } else if (g_strcmp0(method_name, "ReplyPinCode") == 0) {
802                 GapAgentPrivate *priv = user_data;
803                 const char *pin_code;
804                 const guint accept;
805
806                 g_variant_get(parameters, "(u&s)", &accept, &pin_code);
807                 DBG("Accept: %d PinCode: %s", accept, pin_code);
808                 gap_agent_reply_pin_code(priv, accept, pin_code, invocation);
809         } else if (g_strcmp0(method_name, "ReplyPasskey") == 0) {
810                 GapAgentPrivate *priv = user_data;
811                 const char *passkey;
812                 const guint accept;
813
814                 g_variant_get(parameters, "(u&s)", &accept, &passkey);
815                 DBG("Accept: %d PinCode: %s", accept, passkey);
816                 gap_agent_reply_passkey(priv, accept, passkey, invocation);
817         } else if (g_strcmp0(method_name, "ReplyConfirmation") == 0) {
818                 GapAgentPrivate *priv = user_data;
819                 const guint accept;
820
821                 g_variant_get(parameters, "(u)", &accept);
822                 DBG("Accept: %d", accept);
823                 gap_agent_reply_confirmation(priv, accept, invocation);
824         } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
825                 GapAgentPrivate *priv = user_data;
826                 const guint accept;
827
828                 g_variant_get(parameters, "(u)", &accept);
829                 DBG("Accept: %d", accept);
830                 gap_agent_reply_authorize(priv, accept, invocation);
831         }
832         DBG("-");
833 }
834
835 gboolean gap_agent_reply_confirmation(GapAgentPrivate *agent, const guint accept,
836                 GDBusMethodInvocation *context)
837 {
838
839         DBG("+");
840
841         GapAgentPrivate *priv = agent;
842
843         /* Fix : NULL_RETURNS */
844         if (priv == NULL)
845                 return FALSE;
846
847         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
848                         priv->reply_context != NULL) {
849                 if (accept == GAP_AGENT_ACCEPT) {
850                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
851                         priv->canceled = FALSE;
852                 } else {
853                         switch (accept) {
854                                 case GAP_AGENT_CANCEL:
855                                         g_dbus_method_invocation_return_error(priv->reply_context,
856                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
857                                                         "CanceledbyUser");
858                                         priv->canceled = TRUE;
859                                         break;
860                                 case GAP_AGENT_TIMEOUT:
861                                 case GAP_AGENT_REJECT:
862                                 default:
863                                         g_dbus_method_invocation_return_error(priv->reply_context,
864                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
865                                                         "Confirmation request rejected");
866                                         priv->canceled = FALSE;
867                                         break;
868                         }
869                 }
870         }
871
872         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
873         priv->reply_context = NULL;
874         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
875
876         DBG("-");
877         return TRUE;
878 }
879
880 gboolean gap_agent_reply_pin_code(GapAgentPrivate *agent, const guint accept,
881                                                 const char *pin_code,
882                                                 GDBusMethodInvocation *context)
883 {
884         DBG("+");
885         GapAgentPrivate *priv = agent;
886
887         /* Fix : NULL_RETURNS */
888         if (priv == NULL)
889                 return FALSE;
890
891         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
892                         priv->reply_context != NULL) {
893                 if (accept == GAP_AGENT_ACCEPT) {
894                         g_dbus_method_invocation_return_value(priv->reply_context,
895                                         g_variant_new("(s)", pin_code));
896                         priv->canceled = FALSE;
897                 } else {
898                         switch (accept) {
899                                 case GAP_AGENT_CANCEL:
900                                         g_dbus_method_invocation_return_error(priv->reply_context,
901                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
902                                                         "CanceledbyUser");
903                                         priv->canceled = TRUE;
904                                         break;
905                                 case GAP_AGENT_TIMEOUT:
906                                 case GAP_AGENT_REJECT:
907                                 default:
908                                         g_dbus_method_invocation_return_error(priv->reply_context,
909                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
910                                                         "Pairing request rejected");
911                                         priv->canceled = FALSE;
912                                         break;
913                         }
914                 }
915         }
916         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
917         priv->reply_context = NULL;
918         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
919
920         DBG("-");
921         return TRUE;
922 }
923
924 gboolean gap_agent_reply_passkey(GapAgentPrivate *agent, const guint accept,
925                                                 const char *passkey,
926                                                 GDBusMethodInvocation *context)
927 {
928         DBG("+");
929         GapAgentPrivate *priv = agent;
930
931         /* Fix : NULL_RETURNS */
932         if (priv == NULL)
933                 return FALSE;
934
935         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
936                         priv->reply_context != NULL) {
937                 if (accept == GAP_AGENT_ACCEPT) {
938                         guint pass_key = atoi(passkey);
939                         g_dbus_method_invocation_return_value(priv->reply_context,
940                                         g_variant_new("(u)", pass_key));
941                         priv->canceled = FALSE;
942                 } else {
943                         switch (accept) {
944                                 case GAP_AGENT_CANCEL:
945                                         g_dbus_method_invocation_return_error(priv->reply_context,
946                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
947                                                         "CanceledbyUser");
948                                         priv->canceled = TRUE;
949                                         break;
950                                 case GAP_AGENT_TIMEOUT:
951                                 case GAP_AGENT_REJECT:
952                                 default:
953                                         g_dbus_method_invocation_return_error(priv->reply_context,
954                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
955                                                         "Passkey request rejected");
956                                         priv->canceled = FALSE;
957                                         break;
958                         }
959                 }
960         }
961
962         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
963         priv->reply_context = NULL;
964         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
965
966         DBG("-");
967         return TRUE;
968 }
969
970 gboolean gap_agent_reply_authorize(GapAgentPrivate *agent, const guint accept,
971                 GDBusMethodInvocation *context)
972 {
973         gboolean ret = TRUE;
974         GapAgentPrivate *priv = agent;
975         DBG("+");
976
977         /* Fix : NULL_RETURNS */
978         if (priv == NULL)
979                 return  FALSE;
980
981         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
982                         priv->reply_context != NULL) {
983                 if (accept == GAP_AGENT_ACCEPT) {
984                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
985                 } else if (accept == GAP_AGENT_ACCEPT_ALWAYS) {
986                         /* TODO: Enable below logic after set authorization API implementation */
987                         g_dbus_method_invocation_return_value(priv->reply_context, NULL);
988                 } else {
989                         switch (accept) {
990                                 case GAP_AGENT_CANCEL:
991                                         g_dbus_method_invocation_return_error(priv->reply_context,
992                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
993                                                         "CanceledbyUser");
994                                         break;
995                                 case GAP_AGENT_TIMEOUT:
996                                 case GAP_AGENT_REJECT:
997                                 default:
998                                         g_dbus_method_invocation_return_error(priv->reply_context,
999                                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
1000                                                         "Authorization request rejected");
1001                                         break;
1002                         }
1003                 }
1004
1005                 if (context)
1006                         g_dbus_method_invocation_return_value(context, NULL);
1007         } else {
1008                 ERR("No context");
1009                 if (context)
1010                         g_dbus_method_invocation_return_error(context,
1011                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
1012                                         "No context");
1013                 ret = FALSE;
1014         }
1015
1016         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
1017         priv->reply_context = NULL;
1018         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
1019
1020         DBG("-");
1021         return ret;
1022 }