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