Merge the code from private
[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='RequestPinCode'>"
514 "      <arg type='o' name='device' direction='in'/>"
515 "      <arg type='s' name='pincode' direction='out'/>"
516 "    </method>"
517 "    <method name='RequestPasskey'>"
518 "      <arg type='o' name='device' direction='in'/>"
519 "      <arg type='u' name='passkey' direction='out'/>"
520 "    </method>"
521 "    <method name='DisplayPasskey'>"
522 "      <arg type='o' name='device' direction='in'/>"
523 "      <arg type='u' name='passkey' direction='in'/>"
524 "      <arg type='q' name='entered' direction='in'/>"
525 "    </method>"
526 "    <method name='RequestConfirmation'>"
527 "      <arg type='o' name='device' direction='in'/>"
528 "      <arg type='u' name='passkey' direction='in'/>"
529 "    </method>"
530 "    <method name='RequestAuthorization'>"
531 "      <arg type='o' name='device' direction='in'/>"
532 "    </method>"
533 "    <method name='AuthorizeService'>"
534 "      <arg type='o' name='device' direction='in'/>"
535 "      <arg type='s' name='uuid' direction='in'/>"
536 "    </method>"
537 "    <method name='Cancel'>"
538 "    </method>"
539 "    <method name='Release'>"
540 "    </method>"
541 "    <method name='ReplyPinCode'>"
542 "      <arg type='u' name='accept' direction='in'/>"
543 "      <arg type='s' name='pincode' direction='in'/>"
544 "    </method>"
545 "    <method name='ReplyPasskey'>"
546 "      <arg type='u' name='accept' direction='in'/>"
547 "      <arg type='s' name='passkey' direction='in'/>"
548 "    </method>"
549 "    <method name='ReplyConfirmation'>"
550 "      <arg type='u' name='accept' direction='in'/>"
551 "    </method>"
552 "    <method name='ReplyAuthorize'>"
553 "      <arg type='u' name='accept' direction='in'/>"
554 "    </method>"
555 "    <method name='ConfirmModeChange'>"
556 "      <arg type='s' name='mode' direction='in'/>"
557 "    </method>"
558 "    <method name='GetDiscoverableTimeout'>"
559 "      <arg type='u' name='timeout' direction='out'/>"
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_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
658                 agent->cb.pincode_func(agent, device);
659
660                 g_object_unref(device);
661                 return;
662
663         } else if (g_strcmp0(method_name, "RequestPasskey") == 0) {
664                 GapAgentPrivate *priv = user_data;
665                 char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
666                 GDBusProxy *device;
667                 char *addr;
668                 char *path;
669                 GDBusConnection *conn;
670
671                 if (sender == NULL)
672                         return;
673
674                 g_variant_get(parameters, "(&o)", &path);
675                 BT_INFO("Request passkey : sender %s priv->busname %s Device Path :%s",
676                                 sender, priv->busname, path);
677
678                 /* Need to check
679                 if (g_strcmp0(sender, agent->busname) != 0)
680                         return;
681                 */
682
683                 if (!priv->cb.passkey_func)
684                         return;
685
686                 conn = _bt_get_system_gconn();
687                 if (conn == NULL)
688                         return;
689
690                 device = g_dbus_proxy_new_sync(conn,
691                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
692                                 BT_BLUEZ_NAME, path,
693                                 BT_PROPERTIES_INTERFACE, NULL, &err);
694
695                 if (!device) {
696                         BT_ERR("Fail to make device proxy");
697
698                         g_dbus_method_invocation_return_error(invocation,
699                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
700                                         "No proxy for device");
701
702                         if (err) {
703                                 ERR("Unable to create proxy: %s", err->message);
704                                 g_clear_error(&err);
705                         }
706
707                         return;
708                 }
709
710                 priv->exec_type = GAP_AGENT_EXEC_PAIRING;
711                 priv->reply_context = invocation;
712
713                 addr = strstr(path, "dev_");
714                 if (addr != NULL) {
715                         char *pos = NULL;
716                         addr += 4;
717                         g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
718
719                         while ((pos = strchr(priv->pairing_addr, '_')) != NULL) {
720                                 *pos = ':';
721                         }
722                 }
723
724                 priv->cb.passkey_func(priv, device);
725
726                 g_object_unref(device);
727                 return;
728
729         } else if (g_strcmp0(method_name, "DisplayPasskey") == 0) {
730                 GapAgentPrivate *priv = user_data;
731                 char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
732                 GDBusProxy *device;
733                 guint passkey;
734                 guint16 entered;
735                 char *path;
736                 GDBusConnection *conn;
737
738                 if (sender == NULL)
739                         return;
740
741                 g_variant_get(parameters, "(&ouq)", &path, &passkey, &entered);
742                 BT_INFO("Request passkey display :sender %s priv->busname %s"
743                                 " Device Path :%s, Passkey: %06d, Entered: %d",
744                                 sender, priv->busname, path, passkey, entered);
745
746                 /* Do not show popup for Key event while typing*/
747                 if (entered)
748                         return;
749
750                 /* Need to check
751                 if (g_strcmp0(sender, agent->busname) != 0)
752                         return;
753                 */
754
755                 if (!priv->cb.display_func)
756                         return;
757
758                 conn = _bt_get_system_gconn();
759                 if (conn == NULL)
760                         return;
761
762                 device = g_dbus_proxy_new_sync(conn,
763                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
764                                 BT_BLUEZ_NAME, path,
765                                 BT_PROPERTIES_INTERFACE, NULL, &err);
766
767                 if (!device) {
768                         BT_ERR("Fail to make device proxy");
769
770                         g_dbus_method_invocation_return_error(invocation,
771                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
772                                         "No proxy for device");
773
774                         if (err) {
775                                 ERR("Unable to create proxy: %s", err->message);
776                                 g_clear_error(&err);
777                         }
778
779                         return;
780                 }
781
782                 g_dbus_method_invocation_return_value(invocation, NULL);
783
784                 priv->cb.display_func(priv, device, passkey);
785
786                 g_object_unref(device);
787                 return;
788
789         } else if (g_strcmp0(method_name, "RequestConfirmation") == 0) {
790                 GapAgentPrivate *priv = user_data;
791                 char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
792                 GDBusProxy *device;
793                 guint passkey;
794                 char *path;
795                 char *addr;
796                 GDBusConnection *conn;
797
798                 if (sender == NULL)
799                         return;
800
801                 g_variant_get(parameters, "(&ou)", &path, &passkey);
802                 BT_INFO_C("### Request passkey confirmation");
803                 INFO_SECURE("Device Path :%s, Passkey: %d", path, passkey);
804
805                 BT_DBG("Sender: [%s] priv->busname: [%s]", sender, priv->busname);
806                 /* Need to check
807                 if (g_strcmp0(sender, agent->busname) != 0)
808                         return;
809                 */
810
811                 BT_DBG("priv->cb.confirm_func [%p]", priv->cb.confirm_func);
812                 if (!priv->cb.confirm_func)
813                         return;
814
815                 conn = _bt_get_system_gconn();
816                 if (conn == NULL)
817                         return;
818
819                 device = g_dbus_proxy_new_sync(conn,
820                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
821                                 BT_BLUEZ_NAME, path,
822                                 BT_PROPERTIES_INTERFACE, NULL, &err);
823
824                 if (!device) {
825                         BT_ERR("Fail to make device proxy");
826
827                         g_dbus_method_invocation_return_error(invocation,
828                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
829                                         "No proxy for device");
830
831                         if (err) {
832                                 ERR("Unable to create proxy: %s", err->message);
833                                 g_clear_error(&err);
834                         }
835
836                         return;
837                 }
838
839                 priv->exec_type = GAP_AGENT_EXEC_PAIRING;
840                 priv->reply_context = invocation;
841
842                 addr = strstr(path, "dev_");
843                 if (addr != NULL) {
844                         char *pos = NULL;
845                         addr += 4;
846                         g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
847
848                         while ((pos = strchr(priv->pairing_addr, '_')) != NULL) {
849                                 *pos = ':';
850                         }
851                 }
852
853                 priv->cb.confirm_func(priv, device, passkey);
854
855                 g_object_unref(device);
856                 return;
857
858         } else if (g_strcmp0(method_name, "AuthorizeService") == 0) {
859                 GapAgentPrivate *priv = user_data;
860                 char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
861                 GDBusProxy *device;
862                 GDBusConnection *conn;
863                 char *addr;
864                 char *path;
865                 char *uuid;
866
867                 if (sender == NULL)
868                         return;
869
870                 g_variant_get(parameters, "(&o&s)", &path, &uuid);
871                 BT_DBG("Request authorization :sender %s priv->busname %s "
872                                 "Device Path :%s UUID: %s",
873                                 sender, priv->busname, path, uuid);
874
875                 /* Need to check
876                 if (g_strcmp0(sender, agent->busname) != 0)
877                         return;
878                 */
879
880                 if (!priv->cb.authorize_func)
881                         return;
882
883                 conn = _bt_get_system_gconn();
884                 if (conn == NULL)
885                         return;
886
887                 device = g_dbus_proxy_new_sync(conn,
888                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
889                                 BT_BLUEZ_NAME, path,
890                                 BT_PROPERTIES_INTERFACE, NULL, &err);
891
892                 if (!device) {
893                         BT_ERR("Fail to make device proxy");
894
895                         g_dbus_method_invocation_return_error(invocation,
896                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
897                                         "No proxy for device");
898
899                         if (err) {
900                                 ERR("Unable to create proxy: %s", err->message);
901                                 g_clear_error(&err);
902                         }
903
904                         return;
905                 }
906
907                 priv->exec_type = GAP_AGENT_EXEC_AUTHORZATION;
908                 priv->reply_context = invocation;
909                 priv->uuid = g_strdup(uuid);
910
911                 addr = strstr(path, "dev_");
912                 if (addr != NULL) {
913                         char *pos = NULL;
914                         addr += 4;
915                         g_strlcpy(priv->authorize_addr, addr,
916                                                         sizeof(priv->authorize_addr));
917
918                         while ((pos = strchr(priv->authorize_addr, '_')) != NULL) {
919                                 *pos = ':';
920                         }
921                 }
922
923                 priv->cb.authorize_func(priv, device, uuid);
924
925                 g_object_unref(device);
926                 return;
927
928         } else if (g_strcmp0(method_name, "RequestAuthorization") == 0) {
929                 g_dbus_method_invocation_return_value(invocation, NULL);
930         } else if (g_strcmp0(method_name, "ConfirmModeChange") == 0) {
931                 g_dbus_method_invocation_return_value(invocation, NULL);
932         } else if (g_strcmp0(method_name, "Cancel") == 0) {
933                 GapAgentPrivate *priv = user_data;
934                 char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
935
936                 if (sender == NULL)
937                         return;
938
939                 BT_DBG("Cancelled : agent %p sender %s", sender);
940
941                 /* Need to check
942                 if (g_strcmp0(sender, agent->busname) != 0)
943                         return;
944                 */
945
946                 if (priv->cb.authorization_cancel_func &&
947                                 priv->exec_type == GAP_AGENT_EXEC_AUTHORZATION) {
948                         priv->cb.authorization_cancel_func(priv,
949                                                                 priv->authorize_addr);
950                         memset(priv->authorize_addr, 0x00,
951                                                         sizeof(priv->authorize_addr));
952                 } else if (priv->cb.pairing_cancel_func &&
953                                         priv->exec_type == GAP_AGENT_EXEC_PAIRING) {
954                         priv->cb.pairing_cancel_func(priv,
955                                                                 priv->pairing_addr);
956                         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
957                 }
958
959                 if (priv->exec_type != GAP_AGENT_EXEC_CONFIRM_MODE &&
960                                 priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
961                                 priv->reply_context != NULL) {
962
963                         g_dbus_method_invocation_return_error(priv->reply_context,
964                                         GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
965                                         "Rejected by remote cancel");
966                 }
967
968                 /* Canceled flag is set when user cancels pairing request
969                  * Since here bluez has cancelled pairing request, we set the flag to false
970                  */
971                 priv->canceled = FALSE;
972                 priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
973                 priv->reply_context = NULL;
974
975                 return;
976         } else if (g_strcmp0(method_name, "Release") == 0) {
977                 GapAgentPrivate *priv = user_data;
978                 char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
979
980                 if (sender == NULL)
981                         return;
982
983                 BT_DBG("Released : sender %s\n", sender);
984
985                 /* Need to check
986                 if (g_strcmp0(sender, agent->busname) != 0)
987                         return;
988                 */
989
990                 g_dbus_method_invocation_return_value(invocation, NULL);
991
992                 priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
993                 priv->reply_context = NULL;
994
995                 memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
996                 memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
997
998                 return;
999         } else if (g_strcmp0(method_name, "GetDiscoverableTimeout") == 0) {
1000                 BT_DBG("+");
1001
1002                 int timeout;
1003
1004                 _bt_get_timeout_value(&timeout);
1005
1006                 g_dbus_method_invocation_return_value(invocation,
1007                                 g_variant_new("(i)", timeout));
1008
1009                 BT_DBG("-");
1010
1011                 return;
1012         } else if (g_strcmp0(method_name, "ReplyPinCode") == 0) {
1013                 GapAgentPrivate *priv = user_data;
1014                 const char *pin_code;
1015                 const guint accept;
1016
1017                 g_variant_get(parameters, "(u&s)", &accept, &pin_code);
1018                 BT_DBG("Accept: %d PinCode: %s", accept, pin_code);
1019                 gap_agent_reply_pin_code(priv, accept, pin_code, invocation);
1020         } else if (g_strcmp0(method_name, "ReplyPasskey") == 0) {
1021                 GapAgentPrivate *priv = user_data;
1022                 const char *passkey;
1023                 const guint accept;
1024
1025                 g_variant_get(parameters, "(u&s)", &accept, &passkey);
1026                 BT_DBG("Accept: %d PinCode: %s", accept, passkey);
1027                 gap_agent_reply_passkey(priv, accept, passkey, invocation);
1028         } else if (g_strcmp0(method_name, "ReplyConfirmation") == 0) {
1029                 GapAgentPrivate *priv = user_data;
1030                 const guint accept;
1031
1032                 g_variant_get(parameters, "(u)", &accept);
1033                 BT_DBG("Accept: %d", accept);
1034                 gap_agent_reply_confirmation(priv, accept, invocation);
1035         } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
1036                 GapAgentPrivate *priv = user_data;
1037                 const guint accept;
1038
1039                 g_variant_get(parameters, "(u)", &accept);
1040                 BT_DBG("Accept: %d", accept);
1041                 gap_agent_reply_authorize(priv, accept, invocation);
1042         }
1043 }
1044
1045 static const GDBusInterfaceVTable method_table = {
1046         __bt_gap_agent_method,
1047         NULL,
1048         NULL,
1049 };
1050
1051 void _gap_agent_setup_dbus(GapAgentPrivate *agent, GAP_AGENT_FUNC_CB *func_cb,
1052                                                         const char *path,
1053                                                         GDBusProxy *adapter)
1054 {
1055         GapAgentPrivate *priv = agent;
1056         GDBusProxy *proxy;
1057         GDBusNodeInfo *node_info;
1058         GError *error = NULL;
1059
1060         priv->path = g_strdup(path);
1061
1062
1063         node_info = __bt_service_create_method_node_info(
1064                                 gap_agent_bluez_introspection_xml);
1065         if (node_info == NULL)
1066                 return;
1067
1068         BT_DBG("path is [%s]", path);
1069
1070         if (connection == NULL) {
1071                 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1072                 if (!connection) {
1073                         if (error) {
1074                                 ERR("Unable to connect to gdbus: %s", error->message);
1075                                 g_clear_error(&error);
1076                         }
1077                         g_dbus_node_info_unref(node_info);
1078                         return;
1079                 }
1080         }
1081
1082         if (gap_agent_id == -1) {
1083         gap_agent_id = g_dbus_connection_register_object(connection, path,
1084                                         node_info->interfaces[0],
1085                                         &method_table, priv,
1086                                         NULL, &error);
1087         }
1088
1089         g_dbus_node_info_unref(node_info);
1090
1091         if (gap_agent_id == 0) {
1092                 BT_ERR("Failed to register for Path: %s", path);
1093                 if (error) {
1094                         BT_ERR("Failed to register: %s", error->message);
1095                         g_clear_error(&error);
1096                 }
1097                 return;
1098         }
1099
1100         memcpy(&priv->cb, func_cb, sizeof(GAP_AGENT_FUNC_CB));
1101
1102         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
1103         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
1104         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
1105         priv->reply_context = NULL;
1106
1107         BT_DBG("path: %s", path);
1108
1109         proxy =  g_dbus_proxy_new_sync(connection,
1110                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1111                         BT_BLUEZ_NAME, path,
1112                         BT_AGENT_INTERFACE, NULL, &error);
1113
1114         if (!proxy) {
1115                 ERR("Unable to create proxy");
1116                 if (error) {
1117                         ERR("Error: %s", error->message);
1118                         g_clear_error(&error);
1119                 }
1120                 priv->busname = NULL;
1121         } else {
1122                 priv->busname = g_strdup(g_dbus_proxy_get_name(proxy));
1123                 g_object_unref(proxy);
1124                 BT_DBG("Busname: %s", priv->busname);
1125         }
1126
1127 }
1128
1129 void _gap_agent_reset_dbus(GapAgentPrivate *agent)
1130 {
1131         GapAgentPrivate *priv = agent;
1132         if (priv == NULL)
1133                 return;
1134
1135         __gap_agent_unregister(agent);
1136
1137         if (gap_agent_id > 0) {
1138                 g_dbus_connection_unregister_object(connection,
1139                                 gap_agent_id);
1140                 gap_agent_id = -1;
1141         }
1142
1143         if (connection) {
1144                 g_object_unref(connection);
1145                 connection = NULL;
1146         }
1147
1148         if (priv->osp_servers) {
1149                 __gap_agent_remove_osp_servers(priv->osp_servers);
1150                 g_slist_free(priv->osp_servers);
1151                 priv->osp_servers = NULL;
1152         }
1153
1154         g_free(priv->path);
1155         priv->path = NULL;
1156
1157         g_free(priv->busname);
1158         priv->busname = NULL;
1159 }
1160
1161 gboolean _gap_agent_exist_osp_server(GapAgentPrivate *agent, int type, char *uuid)
1162 {
1163         GapAgentPrivate *priv = agent;
1164
1165         if (priv == NULL)
1166                 return FALSE;
1167
1168         if (__gap_agent_find_server(priv->osp_servers,
1169                                 type, uuid) != NULL) {
1170                 return TRUE;
1171         }
1172
1173         return FALSE;
1174 }
1175
1176 bt_agent_osp_server_t *_gap_agent_get_osp_server(GapAgentPrivate *agent, int type,
1177                                         char *uuid)
1178 {
1179         GapAgentPrivate *priv = agent;
1180         bt_agent_osp_server_t *osp_serv = NULL;
1181         if (priv == NULL)
1182                 return NULL;
1183
1184         osp_serv = __gap_agent_find_server(priv->osp_servers,
1185                         type, uuid);
1186         if (!osp_serv) {
1187                 return NULL;
1188         }
1189
1190         return osp_serv;
1191 }
1192
1193 gchar* _gap_agent_get_path(GapAgentPrivate *agent)
1194 {
1195         GapAgentPrivate *priv = agent;
1196         if (priv == NULL)
1197                 return NULL;
1198
1199         return priv->path;
1200 }
1201
1202 gboolean _gap_agent_is_canceled(GapAgentPrivate *agent)
1203 {
1204         GapAgentPrivate *priv = agent;
1205
1206         return priv->canceled;
1207 }
1208
1209 void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value)
1210 {
1211         GapAgentPrivate *priv = agent;
1212         if (priv == NULL)
1213                 return;
1214
1215         priv->canceled = value;
1216 }