3dd00e3908a71bca768f54be9738b51b86b9cbe3
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-gap-agent.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <vconf.h>
24 #include <vconf-keys.h>
25
26 #include "bt-service-common.h"
27 #include "bt-service-agent.h"
28 #include "bt-service-gap-agent.h"
29 #include "bt-service-adapter.h"
30
31 static DBusGConnection *connection = NULL;
32
33 typedef enum {
34         GAP_AGENT_EXEC_NO_OPERATION,
35         GAP_AGENT_EXEC_PAIRING,
36         GAP_AGENT_EXEC_AUTHORZATION,
37         GAP_AGENT_EXEC_CONFIRM_MODE,
38 } GapAgentExecType;
39
40 typedef struct _GapAgentPrivate GapAgentPrivate;
41
42 struct _GapAgentPrivate {
43         gchar *busname;
44         gchar *path;
45         DBusGProxy *adapter;
46         DBusGProxy *agent_manager;
47         DBusGProxy *dbus_proxy;
48
49         GapAgentExecType exec_type;
50         DBusGMethodInvocation *reply_context;
51
52         char pairing_addr[18];
53         char authorize_addr[18];
54
55         GSList *osp_servers;
56
57         GAP_AGENT_FUNC_CB cb;
58         gboolean canceled;
59 };
60
61 G_DEFINE_TYPE(GapAgent, gap_agent, G_TYPE_OBJECT);
62
63 static gboolean gap_agent_request_pin_code(GapAgent *agent,
64                                                 const char *path,
65                                                 DBusGMethodInvocation *context);
66
67 static gboolean gap_agent_request_passkey(GapAgent *agent, const char *path,
68                                                 DBusGMethodInvocation *context);
69
70 static gboolean gap_agent_display_passkey(GapAgent *agent, const char *path,
71                                                 guint passkey,
72                                                 DBusGMethodInvocation *context);
73
74 static gboolean gap_agent_request_confirmation(GapAgent *agent,
75                                                 const char *path,
76                                                 guint passkey,
77                                                 DBusGMethodInvocation *context);
78
79 static gboolean gap_agent_authorize_service(GapAgent *agent, const char *path,
80                                                 const char *uuid,
81                                                 DBusGMethodInvocation *context);
82
83 static gboolean gap_agent_request_authorization(GapAgent *agent,
84                                                 const char *path,
85                                                 DBusGMethodInvocation *context);
86
87 static gboolean gap_agent_cancel(GapAgent *agent,
88                                                 DBusGMethodInvocation *context);
89
90 static gboolean gap_agent_release(GapAgent *agent,
91                                                 DBusGMethodInvocation *context);
92
93 static gboolean gap_agent_confirm_mode_change(GapAgent *agent,
94                                                 const char *mode,
95                                                 DBusGMethodInvocation *context);
96
97 static gboolean gap_agent_get_discoverable_timeout(GapAgent *agent,
98                                                 DBusGMethodInvocation *context);
99
100 #include "bt-gap-agent-method.h"
101
102 typedef enum {
103         GAP_AGENT_ERROR_REJECT,
104         GAP_AGENT_ERROR_CANCEL,
105         GAP_AGENT_ERROR_TIMEOUT,
106 } GapAgentError;
107
108 #define GAP_AGENT_ERROR (gap_agent_error_quark())
109
110 static GQuark gap_agent_error_quark(void)
111 {
112         static GQuark quark = 0;
113         if (!quark)
114                 quark = g_quark_from_static_string("agent");
115
116         return quark;
117 }
118
119 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
120
121 static GError *gap_agent_error(GapAgentError error, const char *err_msg)
122 {
123         return g_error_new(GAP_AGENT_ERROR, error, err_msg, NULL);
124 }
125
126 static void gap_agent_init(GapAgent *agent)
127 {
128         BT_DBG("agent %p\n", agent);
129 }
130
131 static void gap_agent_finalize(GObject *agent)
132 {
133         BT_DBG("Free agent %p\n", agent);
134
135         G_OBJECT_CLASS(gap_agent_parent_class)->finalize(agent);
136 }
137
138 static void gap_agent_class_init(GapAgentClass *klass)
139 {
140         GObjectClass *object_class = (GObjectClass *) klass;
141         GError *error = NULL;
142
143         BT_DBG("class %p\n", klass);
144
145         g_type_class_add_private(klass, sizeof(GapAgentPrivate));
146
147         object_class->finalize = gap_agent_finalize;
148
149         connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
150
151         if (error != NULL) {
152                 g_printerr("Connecting to system bus failed: %s\n",
153                                                                 error->message);
154                 g_error_free(error);
155         }
156
157         dbus_g_object_type_install_info(GAP_TYPE_AGENT,
158                                         &dbus_glib_gap_agent_object_info);
159 }
160
161 GapAgent *_gap_agent_new(void)
162 {
163         GapAgent *agent;
164
165         agent = GAP_GET_AGENT(g_object_new(GAP_TYPE_AGENT, NULL));
166
167         BT_DBG("agent %p\n", agent);
168
169         return agent;
170 }
171
172 static gboolean gap_agent_request_pin_code(GapAgent *agent,
173                                                 const char *path,
174                                                 DBusGMethodInvocation *context)
175 {
176         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
177         char *sender = dbus_g_method_get_sender(context);
178         DBusGProxy *device;
179         DBusGConnection *conn;
180         gboolean result;
181         char *addr;
182
183         if (sender == NULL)
184                 return FALSE;
185
186         BT_DBG("Request PIN : agent %p sender %s priv->busname %s Device Path :%s\n",
187                                 agent, sender, priv->busname, path);
188
189         if (g_strcmp0(sender, priv->busname) != 0) {
190                 g_free(sender);
191                 return FALSE;
192         }
193
194         if (!priv->cb.passkey_func) {
195                 g_free(sender);
196                 return FALSE;
197         }
198
199         conn = _bt_get_system_gconn();
200         if (conn == NULL) {
201                 g_free(sender);
202                 return FALSE;
203         }
204
205         device = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
206                                 path, BT_PROPERTIES_INTERFACE);
207
208         if (device == NULL) {
209                 GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
210                                                         "No proxy for device");
211                 BT_DBG("Fail to make device proxy\n");
212                 dbus_g_method_return_error(context, error);
213                 g_error_free(error);
214                 g_free(sender);
215                 return FALSE;
216         }
217
218         priv->exec_type = GAP_AGENT_EXEC_PAIRING;
219         priv->reply_context = context;
220
221         addr = strstr(path, "dev_");
222         if (addr != NULL) {
223                 char *pos = NULL;
224                 addr += 4;
225                 g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
226
227                 while ((pos = strchr(priv->pairing_addr, '_')) != NULL) {
228                         *pos = ':';
229                 }
230         }
231
232         result = priv->cb.pincode_func(agent, device);
233
234         g_object_unref(device);
235
236         g_free(sender);
237         return result;
238 }
239
240 static gboolean gap_agent_request_passkey(GapAgent *agent, const char *path,
241                                                 DBusGMethodInvocation *context)
242 {
243         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
244         char *sender = dbus_g_method_get_sender(context);
245         DBusGProxy *device;
246         DBusGConnection *conn;
247         gboolean result;
248         char *addr;
249
250         if (sender == NULL)
251                 return FALSE;
252
253         BT_DBG("Request passkey : agent %p sender %s priv->busname %s Device Path :%s\n", agent,
254             sender, priv->busname, path);
255
256         if (g_strcmp0(sender, priv->busname) != 0) {
257                 g_free(sender);
258                 return FALSE;
259         }
260
261         if (!priv->cb.passkey_func) {
262                 g_free(sender);
263                 return FALSE;
264         }
265
266         conn = _bt_get_system_gconn();
267         if (conn == NULL) {
268                 g_free(sender);
269                 return FALSE;
270         }
271
272         device = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
273                                 path, BT_PROPERTIES_INTERFACE);
274
275         if (device == NULL) {
276                 GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
277                                                         "No proxy for device");
278                 BT_DBG("Fail to make device proxy\n");
279                 dbus_g_method_return_error(context, error);
280                 g_error_free(error);
281                 g_free(sender);
282                 return FALSE;
283         }
284
285         priv->exec_type = GAP_AGENT_EXEC_PAIRING;
286         priv->reply_context = context;
287
288         addr = strstr(path, "dev_");
289         if (addr != NULL) {
290                 char *pos = NULL;
291                 addr += 4;
292                 g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
293
294                 while ((pos = strchr(priv->pairing_addr, '_')) != NULL) {
295                         *pos = ':';
296                 }
297         }
298
299         result = priv->cb.passkey_func(agent, device);
300
301         g_object_unref(device);
302
303         g_free(sender);
304         return result;
305
306 }
307
308 static gboolean gap_agent_display_passkey(GapAgent *agent, const char *path,
309                                                 guint passkey,
310                                                 DBusGMethodInvocation *context)
311 {
312         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
313         char *sender = dbus_g_method_get_sender(context);
314         DBusGProxy *device;
315         DBusGConnection *conn;
316         gboolean result;
317
318         if (sender == NULL)
319                 return FALSE;
320
321         BT_DBG("Request passkey display : agent %p sender %s priv->busname %s Device Path :%s\n",
322             agent, sender, priv->busname, path);
323
324         if (g_strcmp0(sender, priv->busname) != 0) {
325                 g_free(sender);
326                 return FALSE;
327         }
328
329         if (!priv->cb.display_func) {
330                 g_free(sender);
331                 return FALSE;
332         }
333
334         conn = _bt_get_system_gconn();
335         if (conn == NULL) {
336                 g_free(sender);
337                 return FALSE;
338         }
339
340         device = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
341                                 path, BT_PROPERTIES_INTERFACE);
342
343         if (device == NULL) {
344                 GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
345                                                         "No proxy for device");
346                 BT_DBG("Fail to make device proxy\n");
347                 dbus_g_method_return_error(context, error);
348                 g_error_free(error);
349                 g_free(sender);
350                 return FALSE;
351         }
352
353         dbus_g_method_return(context);
354
355         result = priv->cb.display_func(agent, device, passkey);
356
357         g_object_unref(device);
358
359         g_free(sender);
360         return result;
361 }
362
363 static gboolean gap_agent_request_confirmation(GapAgent *agent,
364                                                 const char *path,
365                                                 guint passkey,
366                                                 DBusGMethodInvocation *context)
367 {
368         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
369         char *sender = dbus_g_method_get_sender(context);
370         DBusGProxy *device;
371         DBusGConnection *conn;
372         gboolean result;
373         char *addr;
374
375         if (sender == NULL)
376                 return FALSE;
377
378         BT_DBG("Request passkey confirmation : agent %p sender %s priv->busname %s Device Path :%s\n",
379             agent, sender, priv->busname, path);
380
381         if (g_strcmp0(sender, priv->busname) != 0) {
382                 g_free(sender);
383                 return FALSE;
384         }
385
386         if (!priv->cb.confirm_func) {
387                 g_free(sender);
388                 return FALSE;
389         }
390
391         conn = _bt_get_system_gconn();
392         if (conn == NULL) {
393                 g_free(sender);
394                 return FALSE;
395         }
396
397         device = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
398                                 path, BT_PROPERTIES_INTERFACE);
399
400         if (device == NULL) {
401                 GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
402                                                         "No proxy for device");
403                 BT_DBG("Fail to make device proxy\n");
404                 dbus_g_method_return_error(context, error);
405                 g_error_free(error);
406                 g_free(sender);
407                 return FALSE;
408         }
409
410         priv->exec_type = GAP_AGENT_EXEC_PAIRING;
411         priv->reply_context = context;
412
413         addr = strstr(path, "dev_");
414         if (addr != NULL) {
415                 char *pos = NULL;
416                 addr += 4;
417                 g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
418
419                 while ((pos = strchr(priv->pairing_addr, '_')) != NULL) {
420                         *pos = ':';
421                 }
422         }
423
424         result = priv->cb.confirm_func(agent, device, passkey);
425
426         g_object_unref(device);
427
428         g_free(sender);
429         return result;
430 }
431
432 static gboolean gap_agent_authorize_service(GapAgent *agent, const char *path,
433                                                 const char *uuid,
434                                                 DBusGMethodInvocation *context)
435 {
436         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
437         char *sender = dbus_g_method_get_sender(context);
438         DBusGProxy *device;
439         DBusGConnection *conn;
440         gboolean result;
441         char *addr;
442
443         if (sender == NULL)
444                 return FALSE;
445
446         BT_DBG("Request authorization : agent %p sender %s priv->busname %s Device Path :%s\n", agent,
447             sender, priv->busname, path);
448
449         if (g_strcmp0(sender, priv->busname) != 0) {
450                 g_free(sender);
451                 return FALSE;
452         }
453
454         if (!priv->cb.authorize_func) {
455                 g_free(sender);
456                 return FALSE;
457         }
458
459         conn = _bt_get_system_gconn();
460         if (conn == NULL) {
461                 g_free(sender);
462                 return FALSE;
463         }
464
465         device = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
466                                 path, BT_PROPERTIES_INTERFACE);
467
468         if (device == NULL) {
469                 GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
470                                                         "No proxy for device");
471                 BT_DBG("Fail to make device proxy\n");
472                 dbus_g_method_return_error(context, error);
473                 g_error_free(error);
474                 g_free(sender);
475                 return FALSE;
476         }
477
478         priv->exec_type = GAP_AGENT_EXEC_AUTHORZATION;
479         priv->reply_context = context;
480
481         addr = strstr(path, "dev_");
482         if (addr != NULL) {
483                 char *pos = NULL;
484                 addr += 4;
485                 g_strlcpy(priv->authorize_addr, addr,
486                                                 sizeof(priv->authorize_addr));
487
488                 while ((pos = strchr(priv->authorize_addr, '_')) != NULL) {
489                         *pos = ':';
490                 }
491         }
492
493         result = priv->cb.authorize_func(agent, device, uuid);
494
495         g_object_unref(device);
496
497         g_free(sender);
498         return result;
499 }
500
501 static gboolean gap_agent_request_authorization(GapAgent *agent,
502                                                 const char *path,
503                                                 DBusGMethodInvocation *context)
504 {
505         BT_DBG("");
506
507         dbus_g_method_return(context);
508         return TRUE;
509 }
510
511 static gboolean gap_agent_confirm_mode_change(GapAgent *agent,
512                                                 const char *mode,
513                                                 DBusGMethodInvocation *context)
514 {
515         BT_DBG("");
516
517         dbus_g_method_return(context);
518         return TRUE;
519 }
520
521 static gboolean gap_agent_cancel(GapAgent *agent,
522                                                 DBusGMethodInvocation *context)
523 {
524         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
525         char *sender = dbus_g_method_get_sender(context);
526         gboolean result = FALSE;
527
528         if (sender == NULL)
529                 return FALSE;
530
531         BT_DBG("Cancelled : agent %p sender %s\n", agent, sender);
532
533         if (g_strcmp0(sender, priv->busname) != 0) {
534                 g_free(sender);
535                 return FALSE;
536         }
537
538         if (priv->cb.authorization_cancel_func &&
539                         priv->exec_type == GAP_AGENT_EXEC_AUTHORZATION) {
540                 result = priv->cb.authorization_cancel_func(agent,
541                                                         priv->authorize_addr);
542                 memset(priv->authorize_addr, 0x00,
543                                                 sizeof(priv->authorize_addr));
544         } else if (priv->cb.pairing_cancel_func &&
545                                 priv->exec_type == GAP_AGENT_EXEC_PAIRING) {
546                 result = priv->cb.pairing_cancel_func(agent,
547                                                         priv->pairing_addr);
548                 memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
549         }
550
551         if (priv->exec_type != GAP_AGENT_EXEC_CONFIRM_MODE &&
552                         priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
553                                                 priv->reply_context != NULL) {
554                 GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
555                                                 "Rejected by remote cancel");
556                 dbus_g_method_return_error(priv->reply_context, error);
557                 g_error_free(error);
558         }
559
560         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
561         priv->reply_context = NULL;
562
563         g_free(sender);
564         return result;
565 }
566
567 static gboolean gap_agent_release(GapAgent *agent,
568                                                 DBusGMethodInvocation *context)
569 {
570         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
571         char *sender = dbus_g_method_get_sender(context);
572
573         if (sender == NULL)
574                 return FALSE;
575
576         BT_DBG("Released : agent %p sender %s\n", agent, sender);
577
578         if (g_strcmp0(sender, priv->busname) != 0) {
579                 g_free(sender);
580                 return FALSE;
581         }
582
583         dbus_g_method_return(context);
584
585         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
586         priv->reply_context = NULL;
587
588         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
589         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
590
591         g_free(sender);
592         return TRUE;
593 }
594
595 static bt_agent_osp_server_t *__gap_agent_find_server(GSList *servers,
596                                                         int type,
597                                                         const char *uuid)
598 {
599         GSList *l;
600         bt_agent_osp_server_t *transfer;
601
602         for (l = servers; l != NULL; l = l->next) {
603                 transfer = l->data;
604
605                 if (transfer == NULL)
606                         continue;
607
608                 /* No uuid in obex server */
609                 if (type == BT_OBEX_SERVER &&
610                         transfer->type == BT_OBEX_SERVER)
611                         return transfer;
612
613                 if (g_strcmp0(transfer->uuid, uuid) == 0)
614                         return transfer;
615         }
616
617         return NULL;
618 }
619
620 static void __gap_agent_remove_osp_servers(GSList *osp_servers)
621 {
622         GSList *l;
623         bt_agent_osp_server_t *server;
624
625         for (l = osp_servers; l != NULL; l = g_slist_next(l)) {
626                 server = l->data;
627
628                 if (server == NULL)
629                         continue;
630
631                 g_free(server->uuid);
632                 g_free(server);
633         }
634 }
635
636 gboolean _gap_agent_register_osp_server(GapAgent *agent,
637                                                 const gint type,
638                                                 const char *uuid)
639 {
640         bt_agent_osp_server_t *server;
641
642         BT_DBG("+");
643
644         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
645
646         if (priv == NULL)
647                 return FALSE;
648
649         /* type:  BT_OBEX_SERVER / BT_RFCOMM_SERVER*/
650         if (type > BT_RFCOMM_SERVER)
651                 return FALSE;
652
653         server = g_malloc0(sizeof(bt_agent_osp_server_t));
654
655         server->type = type;
656
657         if (type == BT_RFCOMM_SERVER)
658                 server->uuid = g_strdup(uuid);
659
660         priv->osp_servers = g_slist_append(priv->osp_servers, server);
661
662         BT_DBG("-");
663
664         return TRUE;
665 }
666
667 gboolean _gap_agent_unregister_osp_server(GapAgent *agent,
668                                                 const gint type,
669                                                 const char *uuid)
670 {
671         bt_agent_osp_server_t *server;
672
673         BT_DBG("+");
674
675         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
676
677         if (priv == NULL)
678                 return FALSE;
679
680         /* type:  BT_OBEX_SERVER / BT_RFCOMM_SERVER*/
681         if (type > BT_RFCOMM_SERVER)
682                 return FALSE;
683
684         server = __gap_agent_find_server(priv->osp_servers, type, uuid);
685
686         if (server == NULL)
687                 return FALSE;
688
689         priv->osp_servers = g_slist_remove(priv->osp_servers, server);
690
691         g_free(server->uuid);
692         g_free(server);
693
694         BT_DBG("-");
695
696         return TRUE;
697 }
698
699 gboolean gap_agent_reply_pin_code(GapAgent *agent, const guint accept,
700                                                 const char *pin_code,
701                                                 DBusGMethodInvocation *context)
702 {
703         BT_DBG("+\n");
704
705         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
706
707         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
708                                                 priv->reply_context != NULL) {
709                 if (accept == GAP_AGENT_ACCEPT) {
710                         dbus_g_method_return(priv->reply_context, pin_code);
711                         priv->canceled = FALSE;
712                 } else {
713                         GError *error = NULL;
714                         switch (accept) {
715                         case GAP_AGENT_CANCEL:
716                                 error = gap_agent_error(GAP_AGENT_ERROR_CANCEL,
717                                                                 "CanceledbyUser");
718                                 priv->canceled = TRUE;
719                                 break;
720                         case GAP_AGENT_TIMEOUT:
721                         case GAP_AGENT_REJECT:
722                         default:
723                                 error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
724                                                                 "Pairing request rejected");
725                                 priv->canceled = FALSE;
726                                 break;
727                         }
728                         dbus_g_method_return_error(priv->reply_context, error);
729                         g_error_free(error);
730                 }
731         }
732
733         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
734         priv->reply_context = NULL;
735         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
736
737         BT_DBG("-\n");
738
739         return TRUE;
740 }
741
742 gboolean gap_agent_reply_passkey(GapAgent *agent, const guint accept,
743                                                 const char *passkey,
744                                                 DBusGMethodInvocation *context)
745 {
746         BT_DBG("+\n");
747
748         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
749
750         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
751                                                 priv->reply_context != NULL) {
752                 if (accept == GAP_AGENT_ACCEPT) {
753                         guint pass_key = atoi(passkey);
754                         dbus_g_method_return(priv->reply_context, pass_key);
755                         priv->canceled = FALSE;
756                 } else {
757                         GError *error = NULL;
758                         switch (accept) {
759                         case GAP_AGENT_CANCEL:
760                                 error = gap_agent_error(GAP_AGENT_ERROR_CANCEL,
761                                                                 "CanceledbyUser");
762                                 priv->canceled = TRUE;
763                                 break;
764                         case GAP_AGENT_TIMEOUT:
765                         case GAP_AGENT_REJECT:
766                         default:
767                                 error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
768                                                                 "Passkey request rejected");
769                                 priv->canceled = FALSE;
770                                 break;
771                         }
772                         dbus_g_method_return_error(priv->reply_context, error);
773                         g_error_free(error);
774                 }
775         }
776
777         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
778         priv->reply_context = NULL;
779         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
780
781         BT_DBG("-\n");
782
783         return TRUE;
784 }
785
786 gboolean gap_agent_reply_confirmation(GapAgent *agent, const guint accept,
787                                           DBusGMethodInvocation *context)
788 {
789         BT_DBG("+\n");
790
791         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
792
793         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
794                                                 priv->reply_context != NULL) {
795                 if (accept == GAP_AGENT_ACCEPT) {
796                         dbus_g_method_return(priv->reply_context);
797                         priv->canceled = FALSE;
798                 } else {
799                         GError *error = NULL;
800                         switch (accept) {
801                         case GAP_AGENT_CANCEL:
802                                 error = gap_agent_error(GAP_AGENT_ERROR_CANCEL,
803                                                                 "CanceledbyUser");
804                                 priv->canceled = TRUE;
805                                 break;
806                         case GAP_AGENT_TIMEOUT:
807                         case GAP_AGENT_REJECT:
808                         default:
809                                 error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
810                                                                 "Confirmation request rejected");
811                                 priv->canceled = FALSE;
812                                 break;
813                         }
814                         dbus_g_method_return_error(priv->reply_context, error);
815                         g_error_free(error);
816                 }
817         }
818
819         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
820         priv->reply_context = NULL;
821         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
822
823         BT_DBG("-\n");
824
825         return TRUE;
826 }
827
828 gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept,
829                                        DBusGMethodInvocation *context)
830 {
831         gboolean ret = TRUE;
832
833         BT_DBG("+\n");
834
835         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
836
837         if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
838                                                 priv->reply_context != NULL) {
839                 if (accept == GAP_AGENT_ACCEPT) {
840                         dbus_g_method_return(priv->reply_context);
841                 } else {
842                         GError *error = NULL;
843                         switch (accept) {
844                         case GAP_AGENT_CANCEL:
845                                 error = gap_agent_error(GAP_AGENT_ERROR_CANCEL,
846                                                                 "CanceledbyUser");
847                                 break;
848                         case GAP_AGENT_TIMEOUT:
849                         case GAP_AGENT_REJECT:
850                         default:
851                                 error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
852                                                                 "Authorization request rejected");
853                                 break;
854                         }
855                         dbus_g_method_return_error(priv->reply_context, error);
856                         g_error_free(error);
857                 }
858
859                 if (context)
860                         dbus_g_method_return(context);
861         } else {
862                 GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT,
863                                                         "No context");
864                 BT_DBG("No context");
865
866                 if (context)
867                         dbus_g_method_return_error(context, error);
868
869                 g_error_free(error);
870                 ret = FALSE;
871         }
872
873         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
874         priv->reply_context = NULL;
875         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
876
877         BT_DBG("-\n");
878
879         return ret;
880 }
881
882 static gboolean gap_agent_get_discoverable_timeout(GapAgent *agent,
883                                                 DBusGMethodInvocation *context)
884 {
885         BT_DBG("+\n");
886
887         int timeout;
888
889         _bt_get_timeout_value(&timeout);
890
891         dbus_g_method_return(context, timeout);
892
893         BT_DBG("-\n");
894
895         return TRUE;
896 }
897
898 gboolean _gap_agent_register(GapAgent *agent)
899 {
900         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
901         DBusGProxy *agent_manager;
902         GError *error = NULL;
903
904         retv_if(priv == NULL, FALSE);
905         retv_if(connection == NULL, FALSE);
906
907         if (priv->agent_manager == NULL) {
908                 agent_manager = dbus_g_proxy_new_for_name(connection,
909                                         BT_BLUEZ_NAME, BT_BLUEZ_PATH,
910                                         BT_AGENT_MANAGER_INTERFACE);
911
912                 retv_if(agent_manager == NULL, FALSE);
913         } else {
914                 agent_manager = priv->agent_manager;
915         }
916
917         dbus_g_proxy_call(agent_manager, "RegisterAgent", &error,
918                                 DBUS_TYPE_G_OBJECT_PATH, priv->path,
919                                 G_TYPE_STRING, "DisplayYesNo", G_TYPE_INVALID,
920                                 G_TYPE_INVALID);
921         if (error != NULL) {
922                 BT_DBG("Agent registration failed: %s\n", error->message);
923                 g_error_free(error);
924                 g_object_unref(agent_manager);
925                 priv->agent_manager = NULL;
926                 return FALSE;
927         }
928
929         /* Set the defalut agent */
930         dbus_g_proxy_call(agent_manager, "RequestDefaultAgent", &error,
931                                 DBUS_TYPE_G_OBJECT_PATH, priv->path,
932                                 G_TYPE_INVALID, G_TYPE_INVALID);
933
934         if (error != NULL) {
935                 BT_DBG("Request agent failed: %s\n", error->message);
936                 g_error_free(error);
937                 g_object_unref(agent_manager);
938                 priv->agent_manager = NULL;
939                 return FALSE;
940         }
941
942         priv->agent_manager = agent_manager;
943
944         return TRUE;
945 }
946
947 static gboolean __gap_agent_unregister(GapAgent *agent)
948 {
949         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
950         DBusGProxy *agent_manager;
951         GError *error = NULL;
952
953         retv_if(priv == NULL, FALSE);
954         retv_if(priv->path == NULL, FALSE);
955         retv_if(connection == NULL, FALSE);
956
957         if (priv->agent_manager == NULL) {
958                 agent_manager = dbus_g_proxy_new_for_name(connection,
959                                         BT_BLUEZ_NAME, BT_BLUEZ_PATH,
960                                         BT_AGENT_MANAGER_INTERFACE);
961
962                 retv_if(agent_manager == NULL, FALSE);
963         } else {
964                 agent_manager = priv->agent_manager;
965         }
966
967         dbus_g_proxy_call(agent_manager, "UnregisterAgent", &error,
968                                 DBUS_TYPE_G_OBJECT_PATH, priv->path,
969                                 G_TYPE_INVALID, G_TYPE_INVALID);
970
971         g_object_unref(agent_manager);
972         priv->agent_manager = NULL;
973
974         if (error != NULL) {
975                 BT_DBG("Agent unregistration failed: %s\n", error->message);
976                 g_error_free(error);
977                 return FALSE;
978         }
979
980         return TRUE;
981 }
982
983 void _gap_agent_setup_dbus(GapAgent *agent, GAP_AGENT_FUNC_CB *func_cb,
984                                                         const char *path)
985 {
986         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
987         GObject *object;
988         DBusGProxy *proxy;
989
990         priv->path = g_strdup(path);
991
992         object = dbus_g_connection_lookup_g_object(connection, priv->path);
993         if (object != NULL)
994                 g_object_unref(object);
995
996         dbus_g_connection_register_g_object(connection, priv->path,
997                                                         G_OBJECT(agent));
998
999         memcpy(&priv->cb, func_cb, sizeof(GAP_AGENT_FUNC_CB));
1000
1001         priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
1002         memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
1003         memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
1004         priv->reply_context = NULL;
1005
1006         proxy = dbus_g_proxy_new_for_name_owner(connection,
1007                                 BT_BLUEZ_NAME,
1008                                 path,
1009                                 BT_AGENT_INTERFACE,
1010                                 NULL);
1011
1012         if (proxy != NULL) {
1013                 priv->busname = g_strdup(dbus_g_proxy_get_bus_name(proxy));
1014                 g_object_unref(proxy);
1015         } else {
1016                 priv->busname = NULL;
1017         }
1018 }
1019
1020 void _gap_agent_reset_dbus(GapAgent *agent)
1021 {
1022         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
1023
1024         __gap_agent_unregister(agent);
1025
1026         dbus_g_connection_unregister_g_object(connection, G_OBJECT(agent));
1027
1028         if (priv->osp_servers) {
1029                 __gap_agent_remove_osp_servers(priv->osp_servers);
1030                 g_slist_free(priv->osp_servers);
1031                 priv->osp_servers = NULL;
1032         }
1033
1034         if (priv->adapter) {
1035                 g_object_unref(priv->adapter);
1036                 priv->adapter = NULL;
1037         }
1038
1039         g_free(priv->path);
1040         priv->path = NULL;
1041
1042         g_free(priv->busname);
1043         priv->busname = NULL;
1044 }
1045
1046 gboolean _gap_agent_exist_osp_server(GapAgent *agent, int type, char *uuid)
1047 {
1048         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
1049
1050         if (priv == NULL)
1051                 return FALSE;
1052
1053         if (__gap_agent_find_server(priv->osp_servers,
1054                                 type, uuid) != NULL) {
1055                 return TRUE;
1056         }
1057
1058         return FALSE;
1059 }
1060
1061 gchar* _gap_agent_get_path(GapAgent *agent)
1062 {
1063         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
1064
1065         return priv->path;
1066 }
1067
1068 gboolean _gap_agent_is_canceled(GapAgent *agent)
1069 {
1070         GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent);
1071
1072         return priv->canceled;
1073 }