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