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