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