3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2006-2010 Nokia Corporation
6 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
37 #include <dbus/dbus.h>
39 #include "lib/bluetooth.h"
42 #include "gdbus/gdbus.h"
47 #include "dbus-common.h"
51 #include "shared/queue.h"
53 #define IO_CAPABILITY_DISPLAYONLY 0x00
54 #define IO_CAPABILITY_DISPLAYYESNO 0x01
55 #define IO_CAPABILITY_KEYBOARDONLY 0x02
56 #define IO_CAPABILITY_NOINPUTNOOUTPUT 0x03
57 #define IO_CAPABILITY_KEYBOARDDISPLAY 0x04
58 #define IO_CAPABILITY_INVALID 0xFF
60 #define REQUEST_TIMEOUT (60 * 1000) /* 60 seconds */
61 #define AGENT_INTERFACE "org.bluez.Agent1"
63 static GHashTable *agent_list;
64 struct queue *default_agents = NULL;
67 AGENT_REQUEST_PASSKEY,
68 AGENT_REQUEST_CONFIRMATION,
69 AGENT_REQUEST_AUTHORIZATION,
70 AGENT_REQUEST_PINCODE,
71 AGENT_REQUEST_AUTHORIZE_SERVICE,
72 AGENT_REQUEST_DISPLAY_PINCODE,
73 } agent_request_type_t;
80 struct agent_request *request;
84 struct agent_request {
85 agent_request_type_t type;
88 DBusPendingCall *call;
91 GDestroyNotify destroy;
94 static void agent_release(struct agent *agent)
98 DBG("Releasing agent %s, %s", agent->owner, agent->path);
103 message = dbus_message_new_method_call(agent->owner, agent->path,
104 AGENT_INTERFACE, "Release");
105 if (message == NULL) {
106 error("Couldn't allocate D-Bus message");
110 g_dbus_send_message(btd_get_dbus_connection(), message);
113 static int send_cancel_request(struct agent_request *req)
115 DBusMessage *message;
117 DBG("Sending Cancel request to %s, %s", req->agent->owner,
120 message = dbus_message_new_method_call(req->agent->owner, req->agent->path,
121 AGENT_INTERFACE, "Cancel");
122 if (message == NULL) {
123 error("Couldn't allocate D-Bus message");
127 g_dbus_send_message(btd_get_dbus_connection(), message);
132 static void agent_request_free(struct agent_request *req, gboolean destroy)
135 dbus_message_unref(req->msg);
137 dbus_pending_call_unref(req->call);
138 if (req->agent && req->agent->request)
139 req->agent->request = NULL;
140 if (destroy && req->destroy)
141 req->destroy(req->user_data);
145 static void set_io_cap(struct btd_adapter *adapter, gpointer user_data)
147 struct agent *agent = user_data;
151 io_cap = agent->capability;
153 io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
155 adapter_set_io_capability(adapter, io_cap);
158 static bool add_default_agent(struct agent *agent)
160 if (queue_peek_head(default_agents) == agent)
163 queue_remove(default_agents, agent);
165 if (!queue_push_head(default_agents, agent))
168 DBG("Default agent set to %s %s", agent->owner, agent->path);
170 adapter_foreach(set_io_cap, agent);
175 static void remove_default_agent(struct agent *agent)
177 if (queue_peek_head(default_agents) != agent) {
178 queue_remove(default_agents, agent);
182 queue_remove(default_agents, agent);
184 agent = queue_peek_head(default_agents);
186 DBG("Default agent set to %s %s", agent->owner, agent->path);
188 DBG("Default agent cleared");
190 adapter_foreach(set_io_cap, agent);
193 static void agent_disconnect(DBusConnection *conn, void *user_data)
195 struct agent *agent = user_data;
197 DBG("Agent %s disconnected", agent->owner);
199 if (agent->watch > 0) {
200 g_dbus_remove_watch(conn, agent->watch);
204 remove_default_agent(agent);
206 g_hash_table_remove(agent_list, agent->owner);
209 struct agent *agent_ref(struct agent *agent)
213 DBG("%p: ref=%d", agent, agent->ref);
218 void agent_unref(struct agent *agent)
222 DBG("%p: ref=%d", agent, agent->ref);
227 if (agent->request) {
229 agent_pincode_cb pincode_cb;
230 agent_passkey_cb passkey_cb;
233 dbus_error_init(&err);
234 dbus_set_error_const(&err, ERROR_INTERFACE ".Failed",
237 switch (agent->request->type) {
238 case AGENT_REQUEST_PINCODE:
239 pincode_cb = agent->request->cb;
240 pincode_cb(agent, &err, NULL, agent->request->user_data);
242 case AGENT_REQUEST_PASSKEY:
243 passkey_cb = agent->request->cb;
244 passkey_cb(agent, &err, 0, agent->request->user_data);
246 case AGENT_REQUEST_CONFIRMATION:
247 case AGENT_REQUEST_AUTHORIZATION:
248 case AGENT_REQUEST_AUTHORIZE_SERVICE:
249 case AGENT_REQUEST_DISPLAY_PINCODE:
251 cb = agent->request->cb;
252 cb(agent, &err, agent->request->user_data);
255 dbus_error_free(&err);
260 g_free(agent->owner);
266 struct agent *agent_get(const char *owner)
271 agent = g_hash_table_lookup(agent_list, owner);
273 return agent_ref(agent);
276 if (!queue_isempty(default_agents))
277 return agent_ref(queue_peek_head(default_agents));
282 static struct agent *agent_create( const char *name, const char *path,
287 agent = g_new0(struct agent, 1);
289 agent->owner = g_strdup(name);
290 agent->path = g_strdup(path);
291 agent->capability = capability;
293 agent->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
294 name, agent_disconnect,
297 return agent_ref(agent);
300 static struct agent_request *agent_request_new(struct agent *agent,
301 agent_request_type_t type,
304 GDestroyNotify destroy)
306 struct agent_request *req;
308 req = g_new0(struct agent_request, 1);
313 req->user_data = user_data;
314 req->destroy = destroy;
319 int agent_cancel(struct agent *agent)
324 if (agent->request->call) {
325 dbus_pending_call_cancel(agent->request->call);
326 send_cancel_request(agent->request);
329 agent_request_free(agent->request, TRUE);
330 agent->request = NULL;
335 static void simple_agent_reply(DBusPendingCall *call, void *user_data)
337 struct agent_request *req = user_data;
338 struct agent *agent = req->agent;
339 DBusMessage *message;
341 agent_cb cb = req->cb;
343 /* steal_reply will always return non-NULL since the callback
344 * is only called after a reply has been received */
345 message = dbus_pending_call_steal_reply(call);
347 /* Protect from the callback freeing the agent */
350 dbus_error_init(&err);
351 if (dbus_set_error_from_message(&err, message)) {
352 DBG("agent error reply: %s, %s", err.name, err.message);
354 cb(agent, &err, req->user_data);
356 if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
357 error("Timed out waiting for reply from agent");
359 dbus_message_unref(message);
360 dbus_error_free(&err);
365 dbus_error_free(&err);
369 if (!dbus_message_get_args(message, &err, DBUS_TYPE_INVALID)) {
370 error("Wrong reply signature: %s", err.message);
371 cb(agent, &err, req->user_data);
372 dbus_error_free(&err);
376 cb(agent, NULL, req->user_data);
378 dbus_message_unref(message);
380 agent->request = NULL;
381 agent_request_free(req, TRUE);
385 static int agent_call_authorize_service(struct agent_request *req,
386 const char *device_path,
389 struct agent *agent = req->agent;
391 req->msg = dbus_message_new_method_call(agent->owner, agent->path,
392 AGENT_INTERFACE, "AuthorizeService");
394 error("Couldn't allocate D-Bus message");
398 dbus_message_append_args(req->msg,
399 DBUS_TYPE_OBJECT_PATH, &device_path,
400 DBUS_TYPE_STRING, &uuid,
403 if (g_dbus_send_message_with_reply(btd_get_dbus_connection(),
404 req->msg, &req->call,
405 REQUEST_TIMEOUT) == FALSE) {
406 error("D-Bus send failed");
410 dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
414 int agent_authorize_service(struct agent *agent, const char *path,
415 const char *uuid, agent_cb cb,
416 void *user_data, GDestroyNotify destroy)
418 struct agent_request *req;
424 req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZE_SERVICE, cb,
427 err = agent_call_authorize_service(req, path, uuid);
429 agent_request_free(req, FALSE);
433 agent->request = req;
435 DBG("authorize service request was sent for %s", path);
440 static void pincode_reply(DBusPendingCall *call, void *user_data)
442 struct agent_request *req = user_data;
443 struct agent *agent = req->agent;
444 agent_pincode_cb cb = req->cb;
445 DBusMessage *message;
450 /* steal_reply will always return non-NULL since the callback
451 * is only called after a reply has been received */
452 message = dbus_pending_call_steal_reply(call);
454 /* Protect from the callback freeing the agent */
457 dbus_error_init(&err);
458 if (dbus_set_error_from_message(&err, message)) {
459 error("Agent %s replied with an error: %s, %s",
460 agent->path, err.name, err.message);
462 cb(agent, &err, NULL, req->user_data);
463 dbus_error_free(&err);
467 if (!dbus_message_get_args(message, &err,
468 DBUS_TYPE_STRING, &pin,
469 DBUS_TYPE_INVALID)) {
470 error("Wrong passkey reply signature: %s", err.message);
471 cb(agent, &err, NULL, req->user_data);
472 dbus_error_free(&err);
478 if (len > 16 || len < 1) {
479 error("Invalid PIN length (%zu) from agent", len);
480 dbus_set_error_const(&err, ERROR_INTERFACE ".InvalidArgs",
481 "Invalid passkey length");
482 cb(agent, &err, NULL, req->user_data);
483 dbus_error_free(&err);
487 cb(agent, NULL, pin, req->user_data);
491 dbus_message_unref(message);
493 dbus_pending_call_cancel(req->call);
494 agent->request = NULL;
495 agent_request_free(req, TRUE);
499 static int pincode_request_new(struct agent_request *req, const char *device_path,
502 struct agent *agent = req->agent;
504 /* TODO: Add a new method or a new param to Agent interface to request
507 req->msg = dbus_message_new_method_call(agent->owner, agent->path,
508 AGENT_INTERFACE, "RequestPinCode");
509 if (req->msg == NULL) {
510 error("Couldn't allocate D-Bus message");
514 dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
517 if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
518 &req->call, REQUEST_TIMEOUT) == FALSE) {
519 error("D-Bus send failed");
523 dbus_pending_call_set_notify(req->call, pincode_reply, req, NULL);
527 int agent_request_pincode(struct agent *agent, struct btd_device *device,
528 agent_pincode_cb cb, gboolean secure,
529 void *user_data, GDestroyNotify destroy)
531 struct agent_request *req;
532 const char *dev_path = device_get_path(device);
538 req = agent_request_new(agent, AGENT_REQUEST_PINCODE, cb,
541 err = pincode_request_new(req, dev_path, secure);
545 agent->request = req;
550 agent_request_free(req, FALSE);
554 static void passkey_reply(DBusPendingCall *call, void *user_data)
556 struct agent_request *req = user_data;
557 struct agent *agent = req->agent;
558 agent_passkey_cb cb = req->cb;
559 DBusMessage *message;
563 /* steal_reply will always return non-NULL since the callback
564 * is only called after a reply has been received */
565 message = dbus_pending_call_steal_reply(call);
567 dbus_error_init(&err);
568 if (dbus_set_error_from_message(&err, message)) {
569 error("Agent replied with an error: %s, %s",
570 err.name, err.message);
571 cb(agent, &err, 0, req->user_data);
572 dbus_error_free(&err);
576 if (!dbus_message_get_args(message, &err,
577 DBUS_TYPE_UINT32, &passkey,
578 DBUS_TYPE_INVALID)) {
579 error("Wrong passkey reply signature: %s", err.message);
580 cb(agent, &err, 0, req->user_data);
581 dbus_error_free(&err);
585 cb(agent, NULL, passkey, req->user_data);
589 dbus_message_unref(message);
591 dbus_pending_call_cancel(req->call);
592 agent->request = NULL;
593 agent_request_free(req, TRUE);
596 static int passkey_request_new(struct agent_request *req,
597 const char *device_path)
599 struct agent *agent = req->agent;
601 req->msg = dbus_message_new_method_call(agent->owner, agent->path,
602 AGENT_INTERFACE, "RequestPasskey");
603 if (req->msg == NULL) {
604 error("Couldn't allocate D-Bus message");
608 dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
611 if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
612 &req->call, REQUEST_TIMEOUT) == FALSE) {
613 error("D-Bus send failed");
617 dbus_pending_call_set_notify(req->call, passkey_reply, req, NULL);
621 int agent_request_passkey(struct agent *agent, struct btd_device *device,
622 agent_passkey_cb cb, void *user_data,
623 GDestroyNotify destroy)
625 struct agent_request *req;
626 const char *dev_path = device_get_path(device);
632 DBG("Calling Agent.RequestPasskey: name=%s, path=%s",
633 agent->owner, agent->path);
635 req = agent_request_new(agent, AGENT_REQUEST_PASSKEY, cb,
638 err = passkey_request_new(req, dev_path);
642 agent->request = req;
647 agent_request_free(req, FALSE);
651 static int confirmation_request_new(struct agent_request *req,
652 const char *device_path,
655 struct agent *agent = req->agent;
657 req->msg = dbus_message_new_method_call(agent->owner, agent->path,
658 AGENT_INTERFACE, "RequestConfirmation");
659 if (req->msg == NULL) {
660 error("Couldn't allocate D-Bus message");
664 dbus_message_append_args(req->msg,
665 DBUS_TYPE_OBJECT_PATH, &device_path,
666 DBUS_TYPE_UINT32, &passkey,
669 if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
670 &req->call, REQUEST_TIMEOUT) == FALSE) {
671 error("D-Bus send failed");
675 dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
680 int agent_request_confirmation(struct agent *agent, struct btd_device *device,
681 uint32_t passkey, agent_cb cb,
682 void *user_data, GDestroyNotify destroy)
684 struct agent_request *req;
685 const char *dev_path = device_get_path(device);
691 DBG("Calling Agent.RequestConfirmation: name=%s, path=%s, passkey=%06u",
692 agent->owner, agent->path, passkey);
694 req = agent_request_new(agent, AGENT_REQUEST_CONFIRMATION, cb,
697 err = confirmation_request_new(req, dev_path, passkey);
701 agent->request = req;
706 agent_request_free(req, FALSE);
710 static int authorization_request_new(struct agent_request *req,
711 const char *device_path)
713 struct agent *agent = req->agent;
715 req->msg = dbus_message_new_method_call(agent->owner, agent->path,
716 AGENT_INTERFACE, "RequestAuthorization");
717 if (req->msg == NULL) {
718 error("Couldn't allocate D-Bus message");
722 dbus_message_append_args(req->msg,
723 DBUS_TYPE_OBJECT_PATH, &device_path,
726 if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
727 &req->call, REQUEST_TIMEOUT) == FALSE) {
728 error("D-Bus send failed");
732 dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
737 int agent_request_authorization(struct agent *agent, struct btd_device *device,
738 agent_cb cb, void *user_data,
739 GDestroyNotify destroy)
741 struct agent_request *req;
742 const char *dev_path = device_get_path(device);
748 DBG("Calling Agent.RequestAuthorization: name=%s, path=%s",
749 agent->owner, agent->path);
751 req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZATION, cb,
754 err = authorization_request_new(req, dev_path);
758 agent->request = req;
763 agent_request_free(req, FALSE);
767 int agent_display_passkey(struct agent *agent, struct btd_device *device,
768 uint32_t passkey, uint16_t entered)
770 DBusMessage *message;
771 const char *dev_path = device_get_path(device);
773 message = dbus_message_new_method_call(agent->owner, agent->path,
774 AGENT_INTERFACE, "DisplayPasskey");
776 error("Couldn't allocate D-Bus message");
780 dbus_message_append_args(message,
781 DBUS_TYPE_OBJECT_PATH, &dev_path,
782 DBUS_TYPE_UINT32, &passkey,
783 DBUS_TYPE_UINT16, &entered,
786 if (!g_dbus_send_message(btd_get_dbus_connection(), message)) {
787 error("D-Bus send failed");
794 static void display_pincode_reply(DBusPendingCall *call, void *user_data)
796 struct agent_request *req = user_data;
797 struct agent *agent = req->agent;
798 DBusMessage *message;
800 agent_cb cb = req->cb;
802 /* clear agent->request early; our callback will likely try
804 agent->request = NULL;
806 /* steal_reply will always return non-NULL since the callback
807 * is only called after a reply has been received */
808 message = dbus_pending_call_steal_reply(call);
810 dbus_error_init(&err);
811 if (dbus_set_error_from_message(&err, message)) {
812 error("Agent replied with an error: %s, %s",
813 err.name, err.message);
815 cb(agent, &err, req->user_data);
817 if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
819 dbus_message_unref(message);
820 dbus_error_free(&err);
824 dbus_error_free(&err);
828 if (!dbus_message_get_args(message, &err, DBUS_TYPE_INVALID)) {
829 error("Wrong reply signature: %s", err.message);
830 cb(agent, &err, req->user_data);
831 dbus_error_free(&err);
835 cb(agent, NULL, req->user_data);
837 dbus_message_unref(message);
839 agent_request_free(req, TRUE);
842 static int display_pincode_request_new(struct agent_request *req,
843 const char *device_path,
846 struct agent *agent = req->agent;
848 req->msg = dbus_message_new_method_call(agent->owner, agent->path,
849 AGENT_INTERFACE, "DisplayPinCode");
850 if (req->msg == NULL) {
851 error("Couldn't allocate D-Bus message");
855 dbus_message_append_args(req->msg,
856 DBUS_TYPE_OBJECT_PATH, &device_path,
857 DBUS_TYPE_STRING, &pincode,
860 if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
861 &req->call, REQUEST_TIMEOUT) == FALSE) {
862 error("D-Bus send failed");
866 dbus_pending_call_set_notify(req->call, display_pincode_reply,
872 int agent_display_pincode(struct agent *agent, struct btd_device *device,
873 const char *pincode, agent_cb cb,
874 void *user_data, GDestroyNotify destroy)
876 struct agent_request *req;
877 const char *dev_path = device_get_path(device);
883 DBG("Calling Agent.DisplayPinCode: name=%s, path=%s, pincode=%s",
884 agent->owner, agent->path, pincode);
886 req = agent_request_new(agent, AGENT_REQUEST_DISPLAY_PINCODE, cb,
889 err = display_pincode_request_new(req, dev_path, pincode);
893 agent->request = req;
898 agent_request_free(req, FALSE);
902 uint8_t agent_get_io_capability(struct agent *agent)
904 return agent->capability;
907 static void agent_destroy(gpointer data)
909 struct agent *agent = data;
911 DBG("agent %s", agent->owner);
913 if (agent->watch > 0) {
914 g_dbus_remove_watch(btd_get_dbus_connection(), agent->watch);
916 agent_release(agent);
919 remove_default_agent(agent);
924 static uint8_t parse_io_capability(const char *capability)
926 if (g_str_equal(capability, ""))
927 return IO_CAPABILITY_DISPLAYYESNO;
928 if (g_str_equal(capability, "DisplayOnly"))
929 return IO_CAPABILITY_DISPLAYONLY;
930 if (g_str_equal(capability, "DisplayYesNo"))
931 return IO_CAPABILITY_DISPLAYYESNO;
932 if (g_str_equal(capability, "KeyboardOnly"))
933 return IO_CAPABILITY_KEYBOARDONLY;
934 if (g_str_equal(capability, "NoInputNoOutput"))
935 return IO_CAPABILITY_NOINPUTNOOUTPUT;
936 if (g_str_equal(capability, "KeyboardDisplay"))
937 return IO_CAPABILITY_KEYBOARDDISPLAY;
938 return IO_CAPABILITY_INVALID;
941 static DBusMessage *register_agent(DBusConnection *conn,
942 DBusMessage *msg, void *user_data)
945 const char *sender, *path, *capability;
948 sender = dbus_message_get_sender(msg);
950 agent = g_hash_table_lookup(agent_list, sender);
952 return btd_error_already_exists(msg);
954 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
955 DBUS_TYPE_STRING, &capability,
956 DBUS_TYPE_INVALID) == FALSE)
957 return btd_error_invalid_args(msg);
959 cap = parse_io_capability(capability);
960 if (cap == IO_CAPABILITY_INVALID)
961 return btd_error_invalid_args(msg);
963 agent = agent_create(sender, path, cap);
965 return btd_error_invalid_args(msg);
967 DBG("agent %s", agent->owner);
969 g_hash_table_replace(agent_list, agent->owner, agent);
971 return dbus_message_new_method_return(msg);
974 static DBusMessage *unregister_agent(DBusConnection *conn,
975 DBusMessage *msg, void *user_data)
978 const char *sender, *path;
980 sender = dbus_message_get_sender(msg);
982 agent = g_hash_table_lookup(agent_list, sender);
984 return btd_error_does_not_exist(msg);
986 DBG("agent %s", agent->owner);
988 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
989 DBUS_TYPE_INVALID) == FALSE)
990 return btd_error_invalid_args(msg);
992 if (g_str_equal(path, agent->path) == FALSE)
993 return btd_error_does_not_exist(msg);
995 agent_disconnect(conn, agent);
997 return dbus_message_new_method_return(msg);
1000 static DBusMessage *request_default(DBusConnection *conn, DBusMessage *msg,
1003 struct agent *agent;
1004 const char *sender, *path;
1006 sender = dbus_message_get_sender(msg);
1008 agent = g_hash_table_lookup(agent_list, sender);
1010 return btd_error_does_not_exist(msg);
1012 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1013 DBUS_TYPE_INVALID) == FALSE)
1014 return btd_error_invalid_args(msg);
1016 if (g_str_equal(path, agent->path) == FALSE)
1017 return btd_error_does_not_exist(msg);
1019 if (!add_default_agent(agent))
1020 return btd_error_failed(msg, "Failed to set as default");
1022 return dbus_message_new_method_return(msg);
1025 static const GDBusMethodTable methods[] = {
1026 { GDBUS_METHOD("RegisterAgent",
1027 GDBUS_ARGS({ "agent", "o"}, { "capability", "s" }),
1028 NULL, register_agent) },
1029 { GDBUS_METHOD("UnregisterAgent", GDBUS_ARGS({ "agent", "o" }),
1030 NULL, unregister_agent) },
1031 { GDBUS_METHOD("RequestDefaultAgent", GDBUS_ARGS({ "agent", "o" }),
1032 NULL, request_default ) },
1036 void btd_agent_init(void)
1038 agent_list = g_hash_table_new_full(g_str_hash, g_str_equal,
1039 NULL, agent_destroy);
1041 default_agents = queue_new();
1043 g_dbus_register_interface(btd_get_dbus_connection(),
1044 "/org/bluez", "org.bluez.AgentManager1",
1045 methods, NULL, NULL, NULL, NULL);
1048 void btd_agent_cleanup(void)
1050 g_dbus_unregister_interface(btd_get_dbus_connection(),
1051 "/org/bluez", "org.bluez.AgentManager1");
1053 g_hash_table_destroy(agent_list);
1054 queue_destroy(default_agents, NULL);