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