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