summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2009-01-11 10:18:23 -0300
committerJohan Hedberg <johan.hedberg@nokia.com>2009-01-11 19:11:59 +0200
commit2aad1cf41acbc69481915d24cef33fa721d4e1fd (patch)
tree3415f14eb928bc6da4c86bd8600697d31c062c97 /src
parent60ec17b68922904833973af118ff91e0f1df1b04 (diff)
Move bonding creation to device.c.
Diffstat (limited to 'src')
-rw-r--r--src/adapter.c694
-rw-r--r--src/adapter.h36
-rw-r--r--src/dbus-hci.c358
-rw-r--r--src/device.c692
-rw-r--r--src/device.h27
5 files changed, 784 insertions, 1023 deletions
diff --git a/src/adapter.c b/src/adapter.c
index 21db540e..5df012e6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -108,9 +108,6 @@ struct btd_adapter {
GSList *passkey_agents;
struct agent *agent; /* For the new API */
GSList *active_conn;
- struct bonding_request_info *bonding;
- GSList *auth_reqs; /* Received and replied HCI
- authentication requests */
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
GSList *disc_sessions; /* Discovery sessions */
@@ -179,59 +176,6 @@ static inline DBusMessage *unsupported_major_class(DBusMessage *msg)
"Unsupported Major Class");
}
-static DBusHandlerResult error_failed(DBusConnection *conn,
- DBusMessage *msg, const char * desc)
-{
- return error_common_reply(conn, msg, ERROR_INTERFACE ".Failed", desc);
-}
-
-static DBusHandlerResult error_failed_errno(DBusConnection *conn,
- DBusMessage *msg, int err)
-{
- const char *desc = strerror(err);
-
- return error_failed(conn, msg, desc);
-}
-
-static DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn,
- DBusMessage *msg, int err)
-{
- return error_common_reply(conn, msg,
- ERROR_INTERFACE ".ConnectionAttemptFailed",
- err > 0 ? strerror(err) : "Connection attempt failed");
-}
-
-static void bonding_request_free(struct bonding_request_info *bonding)
-{
- struct btd_device *device;
- char address[18];
- struct agent *agent;
-
- if (!bonding)
- return;
-
- if (bonding->msg)
- dbus_message_unref(bonding->msg);
-
- if (bonding->conn)
- dbus_connection_unref(bonding->conn);
-
- if (bonding->io)
- g_io_channel_unref(bonding->io);
-
- ba2str(&bonding->bdaddr, address);
-
- device = adapter_find_device(bonding->adapter, address);
- agent = device_get_agent(device);
-
- if (device && agent) {
- agent_destroy(agent, FALSE);
- device_set_agent(device, NULL);
- }
-
- g_free(bonding);
-}
-
static int active_conn_find_by_bdaddr(const void *data, const void *user_data)
{
const struct active_conn_info *con = data;
@@ -285,62 +229,6 @@ static int found_device_cmp(const struct remote_dev_info *d1,
return 0;
}
-static int auth_req_cmp(const void *p1, const void *p2)
-{
- const struct pending_auth_info *pb1 = p1;
- const bdaddr_t *bda = p2;
-
- return bda ? bacmp(&pb1->bdaddr, bda) : -1;
-}
-
-struct pending_auth_info *adapter_find_auth_request(struct btd_adapter *adapter,
- bdaddr_t *dba)
-{
- GSList *l;
-
- l = g_slist_find_custom(adapter->auth_reqs, dba, auth_req_cmp);
- if (l)
- return l->data;
-
- return NULL;
-}
-
-void adapter_remove_auth_request(struct btd_adapter *adapter, bdaddr_t *dba)
-{
- GSList *l;
- struct pending_auth_info *auth;
-
- l = g_slist_find_custom(adapter->auth_reqs, dba, auth_req_cmp);
- if (!l)
- return;
-
- auth = l->data;
-
- adapter->auth_reqs = g_slist_remove(adapter->auth_reqs, auth);
-
- g_free(auth);
-}
-
-struct pending_auth_info *adapter_new_auth_request(struct btd_adapter *adapter,
- bdaddr_t *dba,
- auth_type_t type)
-{
- struct pending_auth_info *info;
-
- debug("hcid_dbus_new_auth_request");
-
- info = g_new0(struct pending_auth_info, 1);
-
- bacpy(&info->bdaddr, dba);
- info->type = type;
- adapter->auth_reqs = g_slist_append(adapter->auth_reqs, info);
-
- if (adapter->bonding && !bacmp(dba, &adapter->bonding->bdaddr))
- adapter->bonding->auth_active = 1;
-
- return info;
-}
-
static void dev_info_free(struct remote_dev_info *dev)
{
g_free(dev->alias);
@@ -384,91 +272,6 @@ int pending_remote_name_cancel(struct btd_adapter *adapter)
return err;
}
-static int auth_info_agent_cmp(const void *a, const void *b)
-{
- const struct pending_auth_info *auth = a;
- const struct agent *agent = b;
-
- if (auth->agent == agent)
- return 0;
-
- return -1;
-}
-
-static void device_agent_removed(struct agent *agent, void *user_data)
-{
- struct btd_device *device = user_data;
- struct pending_auth_info *auth;
- GSList *l;
- struct btd_adapter *adapter;
-
- adapter = device_get_adapter(device);
- device_set_agent(device, NULL);
-
- l = g_slist_find_custom(adapter->auth_reqs, agent,
- auth_info_agent_cmp);
- if (!l)
- return;
-
- auth = l->data;
- auth->agent = NULL;
-}
-
-static struct bonding_request_info *bonding_request_new(DBusConnection *conn,
- DBusMessage *msg,
- struct btd_adapter *adapter,
- const char *address,
- const char *agent_path,
- uint8_t capability)
-{
- struct bonding_request_info *bonding;
- struct btd_device *device;
- const char *name = dbus_message_get_sender(msg);
- struct agent *agent;
- char addr[18];
- bdaddr_t bdaddr;
-
- debug("bonding_request_new(%s)", address);
-
- device = adapter_get_device(conn, adapter, address);
- if (!device)
- return NULL;
-
- device_get_address(device, &bdaddr);
- ba2str(&bdaddr, addr);
-
- if (adapter->agent &&
- agent_matches(adapter->agent, name, agent_path)) {
- error("Refusing adapter agent usage as device specific one");
- return NULL;
- }
-
- agent = agent_create(adapter, name, agent_path,
- capability,
- device_agent_removed,
- device);
- if (!agent) {
- error("Unable to create a new agent");
- return NULL;
- }
-
- device_set_agent(device, agent);
-
- debug("Temporary agent registered for hci%d/%s at %s:%s",
- adapter->dev_id, addr, name,
- agent_path);
-
- bonding = g_new0(struct bonding_request_info, 1);
-
- bonding->conn = dbus_connection_ref(conn);
- bonding->msg = dbus_message_ref(msg);
- bonding->adapter = adapter;
-
- str2ba(address, &bonding->bdaddr);
-
- return bonding;
-}
-
static int set_limited_discoverable(int dd, const uint8_t *cls, gboolean limited)
{
uint32_t dev_class;
@@ -1079,19 +882,6 @@ static DBusMessage *set_name(DBusConnection *conn, DBusMessage *msg,
return dbus_message_new_method_return(msg);
}
-static void reply_authentication_failure(struct bonding_request_info *bonding)
-{
- DBusMessage *reply;
- int status;
-
- status = bonding->hci_status ?
- bonding->hci_status : HCI_AUTHENTICATION_FAILURE;
-
- reply = new_authentication_return(bonding->msg, status);
- if (reply)
- g_dbus_send_message(bonding->conn, reply);
-}
-
struct btd_device *adapter_find_device(struct btd_adapter *adapter, const char *dest)
{
struct btd_device *device;
@@ -1156,93 +946,6 @@ struct btd_device *adapter_create_device(DBusConnection *conn,
return device;
}
-static DBusMessage *remove_bonding(DBusConnection *conn, DBusMessage *msg,
- const char *address, void *data)
-{
- struct btd_adapter *adapter = data;
- struct btd_device *device;
- char filename[PATH_MAX + 1];
- char *str, srcaddr[18];
- bdaddr_t dst;
- GSList *l;
- int dev;
- gboolean paired;
-
- str2ba(address, &dst);
- ba2str(&adapter->bdaddr, srcaddr);
-
- dev = hci_open_dev(adapter->dev_id);
- if (dev < 0 && msg)
- return no_such_adapter(msg);
-
- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
- "linkkeys");
-
- /* textfile_del doesn't return an error when the key is not found */
- str = textfile_caseget(filename, address);
- paired = str ? TRUE : FALSE;
- g_free(str);
-
- if (!paired && msg) {
- hci_close_dev(dev);
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".DoesNotExist",
- "Bonding does not exist");
- }
-
- /* Delete the link key from storage */
- if (textfile_casedel(filename, address) < 0 && msg) {
- int err = errno;
- hci_close_dev(dev);
- return failed_strerror(msg, err);
- }
-
- /* Delete the link key from the Bluetooth chip */
- hci_delete_stored_link_key(dev, &dst, 0, HCI_REQ_TIMEOUT);
-
- /* find the connection */
- l = g_slist_find_custom(adapter->active_conn, &dst,
- active_conn_find_by_bdaddr);
- if (l) {
- struct active_conn_info *con = l->data;
- /* Send the HCI disconnect command */
- if ((hci_disconnect(dev, htobs(con->handle),
- HCI_OE_USER_ENDED_CONNECTION,
- HCI_REQ_TIMEOUT) < 0)
- && msg){
- int err = errno;
- error("Disconnect failed");
- hci_close_dev(dev);
- return failed_strerror(msg, err);
- }
- }
-
- hci_close_dev(dev);
-
- device = adapter_find_device(adapter, address);
- if (!device)
- goto proceed;
-
- if (paired) {
- gboolean paired = FALSE;
-
- const gchar *dev_path = device_get_path(device);
-
- emit_property_changed(conn, dev_path, DEVICE_INTERFACE,
- "Paired", DBUS_TYPE_BOOLEAN, &paired);
- }
-
-proceed:
- if(!msg)
- goto done;
-
- return dbus_message_new_method_return(msg);
-
-done:
- return NULL;
-}
-
-
void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
struct btd_device *device)
{
@@ -1257,9 +960,6 @@ void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
delete_entry(&adapter->bdaddr, "profiles", dstaddr);
adapter->devices = g_slist_remove(adapter->devices, device);
- if (!device_is_temporary(device))
- remove_bonding(conn, NULL, dstaddr, adapter);
-
adapter_update_devices(adapter);
g_dbus_emit_signal(conn, adapter->path,
@@ -1274,7 +974,7 @@ void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
device_set_agent(device, NULL);
}
- device_remove(conn, device);
+ device_remove(device, conn);
}
struct btd_device *adapter_get_device(DBusConnection *conn,
@@ -1294,292 +994,6 @@ struct btd_device *adapter_get_device(DBusConnection *conn,
return adapter_create_device(conn, adapter, address);
}
-void remove_pending_device(struct btd_adapter *adapter)
-{
- struct btd_device *device;
- char address[18];
-
- ba2str(&adapter->bonding->bdaddr, address);
- device = adapter_find_device(adapter, address);
- if (!device)
- return;
-
- if (device_is_temporary(device))
- adapter_remove_device(adapter->bonding->conn, adapter, device);
-}
-
-static gboolean create_bonding_io_cb(GIOChannel *io, GIOCondition cond,
- struct btd_adapter *adapter)
-{
- struct hci_request rq;
- auth_requested_cp cp;
- evt_cmd_status rp;
- struct l2cap_conninfo cinfo;
- socklen_t len;
- int sk, dd, ret;
-
- if (!adapter->bonding) {
- /* If we come here it implies a bug somewhere */
- debug("create_bonding_io_cb: no pending bonding!");
- g_io_channel_close(io);
- return FALSE;
- }
-
- if (cond & G_IO_NVAL) {
- DBusMessage *reply;
- reply = new_authentication_return(adapter->bonding->msg, 0x09);
- g_dbus_send_message(adapter->bonding->conn, reply);
- goto cleanup;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- debug("Hangup or error on bonding IO channel");
-
- if (!adapter->bonding->auth_active)
- error_connection_attempt_failed(adapter->bonding->conn,
- adapter->bonding->msg,
- ENETDOWN);
- else
- reply_authentication_failure(adapter->bonding);
-
- goto failed;
- }
-
- sk = g_io_channel_unix_get_fd(io);
-
- len = sizeof(ret);
- if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
- error("Can't get socket error: %s (%d)",
- strerror(errno), errno);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
- errno);
- goto failed;
- }
-
- if (ret != 0) {
- if (adapter->bonding->auth_active)
- reply_authentication_failure(adapter->bonding);
- else
- error_connection_attempt_failed(adapter->bonding->conn,
- adapter->bonding->msg,
- ret);
- goto failed;
- }
-
- len = sizeof(cinfo);
- if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) {
- error("Can't get connection info: %s (%d)",
- strerror(errno), errno);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
- errno);
- goto failed;
- }
-
- dd = hci_open_dev(adapter->dev_id);
- if (dd < 0) {
- DBusMessage *reply = no_such_adapter(adapter->bonding->msg);
- g_dbus_send_message(adapter->bonding->conn, reply);
- goto failed;
- }
-
- memset(&rp, 0, sizeof(rp));
-
- memset(&cp, 0, sizeof(cp));
- cp.handle = htobs(cinfo.hci_handle);
-
- memset(&rq, 0, sizeof(rq));
- rq.ogf = OGF_LINK_CTL;
- rq.ocf = OCF_AUTH_REQUESTED;
- rq.cparam = &cp;
- rq.clen = AUTH_REQUESTED_CP_SIZE;
- rq.rparam = &rp;
- rq.rlen = EVT_CMD_STATUS_SIZE;
- rq.event = EVT_CMD_STATUS;
-
- if (hci_send_req(dd, &rq, HCI_REQ_TIMEOUT) < 0) {
- error("Unable to send HCI request: %s (%d)",
- strerror(errno), errno);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
- errno);
- hci_close_dev(dd);
- goto failed;
- }
-
- if (rp.status) {
- error("HCI_Authentication_Requested failed with status 0x%02x",
- rp.status);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
- bt_error(rp.status));
- hci_close_dev(dd);
- goto failed;
- }
-
- hci_close_dev(dd);
-
- adapter->bonding->auth_active = 1;
-
- adapter->bonding->io_id = g_io_add_watch(io,
- G_IO_NVAL | G_IO_HUP | G_IO_ERR,
- (GIOFunc) create_bonding_io_cb,
- adapter);
-
- return FALSE;
-
-failed:
- g_io_channel_close(io);
- remove_pending_device(adapter);
-
-cleanup:
- g_dbus_remove_watch(adapter->bonding->conn,
- adapter->bonding->listener_id);
- bonding_request_free(adapter->bonding);
- adapter->bonding = NULL;
-
- return FALSE;
-}
-
-static void cancel_auth_request(struct pending_auth_info *auth, int dev_id)
-{
- int dd;
-
- if (auth->replied)
- return;
-
- dd = hci_open_dev(dev_id);
- if (dd < 0) {
- error("hci_open_dev: %s (%d)", strerror(errno), errno);
- return;
- }
-
- switch (auth->type) {
- case AUTH_TYPE_PINCODE:
- hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY,
- 6, &auth->bdaddr);
- break;
- case AUTH_TYPE_CONFIRM:
- hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY,
- 6, &auth->bdaddr);
- break;
- case AUTH_TYPE_PASSKEY:
- hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_PASSKEY_NEG_REPLY,
- 6, &auth->bdaddr);
- break;
- case AUTH_TYPE_NOTIFY:
- /* User Notify doesn't require any reply */
- break;
- }
-
- auth->replied = TRUE;
-
- hci_close_dev(dd);
-}
-
-static void cancel_bonding(struct btd_adapter *adapter, gboolean exited)
-{
- struct pending_auth_info *auth;
- struct bonding_request_info *bonding = adapter->bonding;
-
- auth = adapter_find_auth_request(adapter, &adapter->bdaddr);
- if (auth) {
- cancel_auth_request(auth, adapter->dev_id);
- if (auth->agent)
- agent_cancel(auth->agent);
- adapter_remove_auth_request(adapter, &bonding->bdaddr);
- }
-
- remove_pending_device(adapter);
-
- if (bonding->io)
- g_io_channel_close(bonding->io);
-
- if (exited) {
- if (bonding->io_id) {
- g_source_remove(bonding->io_id);
- bonding->io_id = 0;
- }
- bonding_request_free(bonding);
- adapter->bonding = NULL;
-
- } else
- bonding->cancel = TRUE;
-}
-
-static void create_bond_req_exit(DBusConnection *conn, void *user_data)
-{
- struct btd_adapter *adapter = user_data;
-
- debug("CreateConnection requestor exited before bonding was completed");
-
- cancel_bonding(adapter, TRUE);
-}
-
-static DBusMessage *create_bonding(DBusConnection *conn, DBusMessage *msg,
- const char *address, const char *agent_path,
- uint8_t capability, void *data)
-{
- char filename[PATH_MAX + 1];
- char *str, srcaddr[18];
- struct btd_adapter *adapter = data;
- struct bonding_request_info *bonding;
- bdaddr_t dst;
- int sk;
-
- str2ba(address, &dst);
- ba2str(&adapter->bdaddr, srcaddr);
-
- /* check if there is a pending discover: requested by D-Bus/non clients */
- if (adapter->state & STD_INQUIRY)
- return in_progress(msg, "Discover in progress");
-
- pending_remote_name_cancel(adapter);
-
- if (adapter->bonding)
- return in_progress(msg, "Bonding in progress");
-
- if (adapter_find_auth_request(adapter, &dst))
- return in_progress(msg, "Bonding in progress");
-
- /* check if a link key already exists */
- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
- "linkkeys");
-
- str = textfile_caseget(filename, address);
- if (str) {
- free(str);
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".AlreadyExists",
- "Bonding already exists");
- }
-
- sk = l2raw_connect(&adapter->bdaddr, &dst);
- if (sk < 0)
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".ConnectionAttemptFailed",
- "Connection attempt failed");
-
- bonding = bonding_request_new(conn, msg, adapter, address, agent_path,
- capability);
- if (!bonding) {
- close(sk);
- return NULL;
- }
-
- bonding->io = g_io_channel_unix_new(sk);
- bonding->io_id = g_io_add_watch(bonding->io,
- G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
- (GIOFunc) create_bonding_io_cb,
- adapter);
-
- bonding->listener_id = g_dbus_add_disconnect_watch(conn,
- dbus_message_get_sender(msg),
- create_bond_req_exit, adapter,
- NULL);
-
- adapter->bonding = bonding;
-
- return NULL;
-}
-
static int start_inquiry(struct btd_adapter *adapter)
{
inquiry_cp cp;
@@ -2010,9 +1424,8 @@ static DBusMessage *cancel_device_creation(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct btd_adapter *adapter = data;
- struct bonding_request_info *bonding = adapter->bonding;
const gchar *address;
- bdaddr_t bda;
+ struct btd_device *device;
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
DBUS_TYPE_INVALID) == FALSE)
@@ -2021,16 +1434,17 @@ static DBusMessage *cancel_device_creation(DBusConnection *conn,
if (check_address(address) < 0)
return invalid_args(msg);
- str2ba(address, &bda);
+ device = adapter_find_device(adapter, address);
+ if (!device)
+ return g_dbus_create_error(msg,
+ ERROR_INTERFACE ".DoesNotExist",
+ "Device does not exist");
- if (bonding && !bacmp(&bonding->bdaddr, &bda)) {
- if (!g_str_equal(dbus_message_get_sender(msg),
- dbus_message_get_sender(bonding->msg)))
- return not_authorized(msg);
+ if (!device_is_temporary(device) ||
+ !device_is_bonding(device, dbus_message_get_sender(msg)))
+ return not_authorized(msg);
- debug("Canceling device creation for %s", address);
- cancel_bonding(adapter, FALSE);
- }
+ adapter_remove_device(conn, adapter, device);
return dbus_message_new_method_return(msg);
}
@@ -2085,7 +1499,9 @@ static uint8_t parse_io_capability(const char *capability)
static DBusMessage *create_paired_device(DBusConnection *conn,
DBusMessage *msg, void *data)
{
- const gchar *address, *agent_path, *capability;
+ struct btd_adapter *adapter = data;
+ struct btd_device *device;
+ const gchar *address, *agent_path, *capability, *sender;
uint8_t cap;
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
@@ -2097,11 +1513,20 @@ static DBusMessage *create_paired_device(DBusConnection *conn,
if (check_address(address) < 0)
return invalid_args(msg);
+ sender = dbus_message_get_sender(msg);
+ if (adapter->agent &&
+ agent_matches(adapter->agent, sender, agent_path)) {
+ error("Refusing adapter agent usage as device specific one");
+ return invalid_args(msg);
+ }
+
cap = parse_io_capability(capability);
if (cap == IO_CAPABILITY_INVALID)
return invalid_args(msg);
- return create_bonding(conn, msg, address, agent_path, cap, data);
+ device = adapter_get_device(conn, adapter, address);
+
+ return device_create_bonding(device, conn, msg, agent_path, cap);
}
static gint device_path_cmp(struct btd_device *device, const gchar *path)
@@ -2179,18 +1604,7 @@ static DBusMessage *find_device(DBusConnection *conn,
static void agent_removed(struct agent *agent, struct btd_adapter *adapter)
{
- struct pending_auth_info *auth;
- GSList *l;
-
adapter->agent = NULL;
-
- l = g_slist_find_custom(adapter->auth_reqs, agent,
- auth_info_agent_cmp);
- if (!l)
- return;
-
- auth = l->data;
- auth->agent = NULL;
}
static DBusMessage *register_agent(DBusConnection *conn,
@@ -2725,27 +2139,18 @@ setup:
static void reply_pending_requests(struct btd_adapter *adapter)
{
- DBusMessage *reply;
+ GSList *l;
if (!adapter)
return;
/* pending bonding */
- if (adapter->bonding) {
- reply = new_authentication_return(adapter->bonding->msg,
- HCI_OE_USER_ENDED_CONNECTION);
- g_dbus_send_message(connection, reply);
- remove_pending_device(adapter);
-
- g_dbus_remove_watch(adapter->bonding->conn,
- adapter->bonding->listener_id);
+ for (l = adapter->devices; l; l = l->next) {
+ struct btd_device *device = l->data;
- if (adapter->bonding->io_id)
- g_source_remove(adapter->bonding->io_id);
- if (adapter->bonding->io)
- g_io_channel_close(adapter->bonding->io);
- bonding_request_free(adapter->bonding);
- adapter->bonding = NULL;
+ if (device_is_bonding(device, NULL))
+ device_cancel_bonding(device,
+ HCI_OE_USER_ENDED_CONNECTION);
}
if (adapter->state & STD_INQUIRY) {
@@ -2806,12 +2211,6 @@ int adapter_stop(struct btd_adapter *adapter)
adapter->oor_devices = NULL;
}
- if (adapter->auth_reqs) {
- g_slist_foreach(adapter->auth_reqs, (GFunc) g_free, NULL);
- g_slist_free(adapter->auth_reqs);
- adapter->auth_reqs = NULL;
- }
-
if (adapter->active_conn) {
g_slist_foreach(adapter->active_conn, (GFunc) g_free, NULL);
g_slist_free(adapter->active_conn);
@@ -2958,7 +2357,7 @@ void adapter_remove(struct btd_adapter *adapter)
unload_drivers(adapter);
for (l = adapter->devices; l; l = l->next)
- device_remove(connection, l->data);
+ device_remove(l->data, connection);
g_slist_free(adapter->devices);
/* Return adapter to down state if it was not up on init */
@@ -3304,29 +2703,6 @@ struct active_conn_info *adapter_search_active_conn_by_handle(struct btd_adapter
return NULL;
}
-void adapter_free_bonding_request(struct btd_adapter *adapter)
-{
- g_dbus_remove_watch(connection, adapter->bonding->listener_id);
-
- if (adapter->bonding->io_id)
- g_source_remove(adapter->bonding->io_id);
-
- if (adapter->bonding->io)
- g_io_channel_close(adapter->bonding->io);
-
- bonding_request_free(adapter->bonding);
-
- adapter->bonding = NULL;
-}
-
-struct bonding_request_info *adapter_get_bonding_info(struct btd_adapter *adapter)
-{
- if (!adapter)
- return NULL;
-
- return adapter->bonding;
-}
-
gboolean adapter_has_discov_sessions(struct btd_adapter *adapter)
{
if (!adapter || !adapter->disc_sessions)
@@ -3521,11 +2897,3 @@ gboolean adapter_is_pairable(struct btd_adapter *adapter)
{
return adapter->pairable;
}
-
-gboolean adapter_pairing_initiator(struct btd_adapter *adapter, bdaddr_t *bda)
-{
- if (!adapter->bonding)
- return FALSE;
-
- return (bacmp(&adapter->bonding->bdaddr, bda) == 0);
-}
diff --git a/src/adapter.h b/src/adapter.h
index 0ca6842c..2f9068f2 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -43,12 +43,7 @@ typedef enum {
NAME_SENT /* D-Bus signal RemoteNameUpdated sent */
} name_status_t;
-typedef enum {
- AUTH_TYPE_PINCODE,
- AUTH_TYPE_PASSKEY,
- AUTH_TYPE_CONFIRM,
- AUTH_TYPE_NOTIFY,
-} auth_type_t;
+struct btd_adapter;
struct remote_dev_info {
bdaddr_t bdaddr;
@@ -58,26 +53,6 @@ struct remote_dev_info {
name_status_t name_status;
};
-struct bonding_request_info {
- DBusConnection *conn;
- DBusMessage *msg;
- struct btd_adapter *adapter;
- bdaddr_t bdaddr;
- GIOChannel *io;
- guint io_id;
- guint listener_id;
- int hci_status;
- int cancel;
- int auth_active;
-};
-
-struct pending_auth_info {
- auth_type_t type;
- bdaddr_t bdaddr;
- gboolean replied; /* If we've already replied to the request */
- struct agent *agent; /* Agent associated with the request */
-};
-
struct active_conn_info {
bdaddr_t bdaddr;
uint16_t handle;
@@ -123,12 +98,6 @@ int pending_remote_name_cancel(struct btd_adapter *adapter);
void remove_pending_device(struct btd_adapter *adapter);
-struct pending_auth_info *adapter_find_auth_request(struct btd_adapter *adapter,
- bdaddr_t *dba);
-void adapter_remove_auth_request(struct btd_adapter *adapter, bdaddr_t *dba);
-struct pending_auth_info *adapter_new_auth_request(struct btd_adapter *adapter,
- bdaddr_t *dba,
- auth_type_t type);
struct btd_adapter *adapter_create(DBusConnection *conn, int id,
gboolean devup);
void adapter_remove(struct btd_adapter *adapter);
@@ -155,8 +124,6 @@ struct active_conn_info *adapter_search_active_conn_by_bdaddr(struct btd_adapter
bdaddr_t *bda);
struct active_conn_info *adapter_search_active_conn_by_handle(struct btd_adapter *adapter,
uint16_t handle);
-void adapter_free_bonding_request(struct btd_adapter *adapter);
-struct bonding_request_info *adapter_get_bonding_info(struct btd_adapter *adapter);
gboolean adapter_has_discov_sessions(struct btd_adapter *adapter);
struct btd_adapter_driver {
@@ -178,4 +145,3 @@ const char *adapter_any_get_path(void);
const char *btd_adapter_any_request_path(void);
void btd_adapter_any_release_path(void);
gboolean adapter_is_pairable(struct btd_adapter *adapter);
-gboolean adapter_pairing_initiator(struct btd_adapter *adapter, bdaddr_t *bda);
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index 7432f018..0e574aff 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -119,54 +119,6 @@ const char *class_to_icon(uint32_t class)
return NULL;
}
-DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
-{
- switch (status) {
- case 0x00: /* success */
- return dbus_message_new_method_return(msg);
-
- case 0x04: /* page timeout */
- case 0x08: /* connection timeout */
- case 0x10: /* connection accept timeout */
- case 0x22: /* LMP response timeout */
- case 0x28: /* instant passed - is this a timeout? */
- return dbus_message_new_error(msg,
- ERROR_INTERFACE ".AuthenticationTimeout",
- "Authentication Timeout");
- case 0x17: /* too frequent pairing attempts */
- return dbus_message_new_error(msg,
- ERROR_INTERFACE ".RepeatedAttempts",
- "Repeated Attempts");
-
- case 0x06:
- case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */
- return dbus_message_new_error(msg,
- ERROR_INTERFACE ".AuthenticationRejected",
- "Authentication Rejected");
-
- case 0x07: /* memory capacity */
- case 0x09: /* connection limit */
- case 0x0a: /* synchronous connection limit */
- case 0x0d: /* limited resources */
- case 0x13: /* user ended the connection */
- case 0x14: /* terminated due to low resources */
- return dbus_message_new_error(msg,
- ERROR_INTERFACE ".AuthenticationCanceled",
- "Authentication Canceled");
-
- case 0x05: /* authentication failure */
- case 0x0E: /* rejected due to security reasons - is this auth failure? */
- case 0x25: /* encryption mode not acceptable - is this auth failure? */
- case 0x26: /* link key cannot be changed - is this auth failure? */
- case 0x29: /* pairing with unit key unsupported - is this auth failure? */
- case 0x2f: /* insufficient security - is this auth failure? */
- default:
- return dbus_message_new_error(msg,
- ERROR_INTERFACE ".AuthenticationFailed",
- "Authentication Failed");
- }
-}
-
/*****************************************************************
*
* Section reserved to HCI commands confirmation handling and low
@@ -182,13 +134,7 @@ static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,
bdaddr_t sba, dba;
size_t len;
int dev;
- struct pending_auth_info *auth;
uint16_t dev_id = adapter_get_dev_id(adapter);
- struct bonding_request_info *bonding = adapter_get_bonding_info(adapter);
-
- /* No need to reply anything if the authentication already failed */
- if (bonding && bonding->hci_status)
- return;
dev = hci_open_dev(dev_id);
if (dev < 0) {
@@ -200,8 +146,6 @@ static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,
adapter_get_address(adapter, &sba);
device_get_address(device, &dba);
- auth = adapter_find_auth_request(adapter, &dba);
-
if (err) {
hci_send_cmd(dev, OGF_LINK_CTL,
OCF_PIN_CODE_NEG_REPLY, 6, &dba);
@@ -219,10 +163,6 @@ static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,
hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr);
done:
- if (auth) {
- auth->replied = TRUE;
- auth->agent = NULL;
- }
hci_close_dev(dev);
}
@@ -231,8 +171,6 @@ int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
char addr[18];
struct btd_adapter *adapter;
struct btd_device *device;
- struct agent *agent = NULL;
- int ret;
adapter = manager_find_adapter(sba);
if (!adapter) {
@@ -240,42 +178,21 @@ int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
return -1;
}
- if (!adapter_pairing_initiator(adapter, &ci->bdaddr) &&
- !adapter_is_pairable(adapter))
- return -EPERM;
-
ba2str(&ci->bdaddr, addr);
device = adapter_find_device(adapter, addr);
-
- if (device)
- agent = device_get_agent(device);
-
- if (!agent)
- agent = adapter_get_agent(adapter);
-
- if (!agent) {
- error("No agent available for PIN request");
+ /* Check if the adapter is not pairable and if there isn't a bonding in
+ * progress */
+ if (!adapter_is_pairable(adapter) &&
+ !(device && device_is_bonding(device, NULL)))
return -EPERM;
- }
- if (!device) {
- device = adapter_create_device(connection, adapter, addr);
- if (!device)
- return -ENODEV;
- }
-
- ret = agent_request_pincode(agent, device,
- (agent_pincode_cb) pincode_cb,
- device);
- if (ret == 0) {
- struct pending_auth_info *auth;
- auth = adapter_new_auth_request(adapter, &ci->bdaddr,
- AUTH_TYPE_PINCODE);
- auth->agent = agent;
- }
+ device = adapter_get_device(connection, adapter, addr);
+ if (!device)
+ return -ENODEV;
- return ret;
+ return device_request_authentication(device, AUTH_TYPE_PINCODE,
+ 0, pincode_cb);
}
static void confirm_cb(struct agent *agent, DBusError *err, void *user_data)
@@ -284,13 +201,7 @@ static void confirm_cb(struct agent *agent, DBusError *err, void *user_data)
struct btd_adapter *adapter = device_get_adapter(device);
user_confirm_reply_cp cp;
int dd;
- struct pending_auth_info *auth;
uint16_t dev_id = adapter_get_dev_id(adapter);
- struct bonding_request_info *bonding = adapter_get_bonding_info(adapter);
-
- /* No need to reply anything if the authentication already failed */
- if (bonding && bonding->hci_status)
- return;
dd = hci_open_dev(dev_id);
if (dd < 0) {
@@ -301,8 +212,6 @@ static void confirm_cb(struct agent *agent, DBusError *err, void *user_data)
memset(&cp, 0, sizeof(cp));
device_get_address(device, &cp.bdaddr);
- auth = adapter_find_auth_request(adapter, &cp.bdaddr);
-
if (err)
hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY,
USER_CONFIRM_REPLY_CP_SIZE, &cp);
@@ -310,11 +219,6 @@ static void confirm_cb(struct agent *agent, DBusError *err, void *user_data)
hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_REPLY,
USER_CONFIRM_REPLY_CP_SIZE, &cp);
- if (auth) {
- auth->replied = TRUE;
- auth->agent = FALSE;
- }
-
hci_close_dev(dd);
}
@@ -326,13 +230,7 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
user_passkey_reply_cp cp;
bdaddr_t dba;
int dd;
- struct pending_auth_info *auth;
uint16_t dev_id = adapter_get_dev_id(adapter);
- struct bonding_request_info *bonding = adapter_get_bonding_info(adapter);
-
- /* No need to reply anything if the authentication already failed */
- if (bonding && bonding->hci_status)
- return;
dd = hci_open_dev(dev_id);
if (dd < 0) {
@@ -346,8 +244,6 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
bacpy(&cp.bdaddr, &dba);
cp.passkey = passkey;
- auth = adapter_find_auth_request(adapter, &dba);
-
if (err)
hci_send_cmd(dd, OGF_LINK_CTL,
OCF_USER_PASSKEY_NEG_REPLY, 6, &dba);
@@ -355,11 +251,6 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_PASSKEY_REPLY,
USER_PASSKEY_REPLY_CP_SIZE, &cp);
- if (auth) {
- auth->replied = TRUE;
- auth->agent = NULL;
- }
-
hci_close_dev(dd);
}
@@ -403,10 +294,8 @@ int hcid_dbus_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
{
struct btd_adapter *adapter;
struct btd_device *device;
- struct agent *agent;
char addr[18];
uint8_t type;
- struct pending_auth_info *auth;
uint16_t dev_id;
adapter = manager_find_adapter(sba);
@@ -457,41 +346,19 @@ int hcid_dbus_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
hci_close_dev(dd);
- auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_CONFIRM);
- auth->replied = TRUE;
-
- return 0;
- }
-
- agent = device_get_agent(device);
-
- if (!agent)
- agent = adapter_get_agent(adapter);
-
- if (!agent) {
- error("No agent available for user confirm request");
- return -1;
- }
-
- if (agent_request_confirmation(agent, device, passkey,
- confirm_cb, device) < 0) {
- error("Requesting passkey failed");
- return -1;
+ return device_request_authentication(device, AUTH_TYPE_AUTO,
+ 0, NULL);
}
- auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_CONFIRM);
- auth->agent = agent;
-
- return 0;
+ return device_request_authentication(device, AUTH_TYPE_CONFIRM,
+ passkey, confirm_cb);
}
int hcid_dbus_user_passkey(bdaddr_t *sba, bdaddr_t *dba)
{
struct btd_adapter *adapter;
struct btd_device *device;
- struct agent *agent = NULL;
char addr[18];
- struct pending_auth_info *auth;
adapter = manager_find_adapter(sba);
if (!adapter) {
@@ -503,35 +370,18 @@ int hcid_dbus_user_passkey(bdaddr_t *sba, bdaddr_t *dba)
device = adapter_get_device(connection, adapter, addr);
- if (device)
- agent = device_get_agent(device);
-
- if (!agent)
- agent = adapter_get_agent(adapter);
-
- if (!agent) {
- error("No agent available for user passkey request");
- return -1;
- }
-
- if (agent_request_passkey(agent, device, passkey_cb, device) < 0) {
- error("Requesting passkey failed");
- return -1;
- }
-
- auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_PASSKEY);
- auth->agent = agent;
+ if (!device)
+ return -ENODEV;
- return 0;
+ return device_request_authentication(device, AUTH_TYPE_PASSKEY,
+ 0, passkey_cb);
}
int hcid_dbus_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
{
struct btd_adapter *adapter;
struct btd_device *device;
- struct agent *agent = NULL;
char addr[18];
- struct pending_auth_info *auth;
adapter = manager_find_adapter(sba);
if (!adapter) {
@@ -542,26 +392,11 @@ int hcid_dbus_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
ba2str(dba, addr);
device = adapter_get_device(connection, adapter, addr);
- if (device)
- agent = device_get_agent(device);
-
- if (!agent)
- agent = adapter_get_agent(adapter);
-
- if (!agent) {
- error("No agent available for user confirm request");
- return -1;
- }
-
- if (agent_display_passkey(agent, device, passkey) < 0) {
- error("Displaying passkey failed");
- return -1;
- }
-
- auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_NOTIFY);
- auth->agent = agent;
+ if (!device)
+ return -ENODEV;
- return 0;
+ return device_request_authentication(device, AUTH_TYPE_NOTIFY,
+ passkey, NULL);
}
void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
@@ -569,74 +404,35 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
{
struct btd_adapter *adapter;
char peer_addr[18];
- DBusMessage *reply;
struct btd_device *device;
- struct bonding_request_info *bonding;
- struct pending_auth_info *auth;
debug("hcid_dbus_bonding_process_complete: status=%02x", status);
- ba2str(peer, peer_addr);
-
adapter = manager_find_adapter(local);
if (!adapter) {
error("Unable to find matching adapter");
return;
}
- bonding = adapter_get_bonding_info(adapter);
-
- if (bonding && bacmp(&bonding->bdaddr, peer))
- bonding = NULL;
+ ba2str(peer, peer_addr);
- if (status == 0) {
- device = adapter_get_device(connection, adapter, peer_addr);
- if (!device) {
- /* This should really only happen if we run out of
- * memory */
- error("Unable to get device object!");
- status = HCI_REJECTED_LIMITED_RESOURCES;
- }
+ device = adapter_find_device(adapter, peer_addr);
+ if (!device) {
+ error("Unable to get device object!");
+ return;
}
- if (status && bonding)
- bonding->hci_status = status;
-
- auth = adapter_find_auth_request(adapter, peer);
- if (!auth) {
- /* This means that there was no pending PIN or SSP token request
- * from the controller, i.e. this is not a new pairing */
+ if (!device_is_authenticating(device)) {
+ /* This means that there was no pending PIN or SSP token
+ * request from the controller, i.e. this is not a new
+ * pairing */
debug("hcid_dbus_bonding_process_complete: no pending auth request");
- goto proceed;
- }
-
- if (auth->agent)
- agent_cancel(auth->agent);
-
- adapter_remove_auth_request(adapter, peer);
-
- /* If this is a new pairing send the appropriate signal for it
- * and proceed with service discovery */
- if (status == 0) {
- device_set_paired(connection, device, bonding);
- if (bonding)
- adapter_free_bonding_request(adapter);
return;
}
-proceed:
- if (!bonding)
- return; /* skip: no bonding req pending */
-
- if (bonding->cancel)
- reply = new_authentication_return(bonding->msg,
- HCI_OE_USER_ENDED_CONNECTION);
- else
- reply = new_authentication_return(bonding->msg, status);
-
- g_dbus_send_message(connection, reply);
-
- adapter_free_bonding_request(adapter);
+ /* If this is a new pairing send the appropriate reply and signal for
+ * it and proceed with service discovery */
+ device_bonding_complete(device, status);
}
void hcid_dbus_inquiry_start(bdaddr_t *local)
@@ -1125,7 +921,6 @@ void hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer)
char peer_addr[18];
struct btd_device *device;
struct btd_adapter *adapter;
- struct bonding_request_info *bonding;
adapter = manager_find_adapter(local);
if (!adapter) {
@@ -1141,11 +936,9 @@ void hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer)
return;
}
- bonding = adapter_get_bonding_info(adapter);
-
if (!device_get_connected(device))
device_set_secmode3_conn(device, TRUE);
- else if (!bonding)
+ else if (!device_is_bonding(device, NULL))
hcid_dbus_bonding_process_complete(local, peer, 0);
}
@@ -1154,7 +947,6 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle,
{
char peer_addr[18];
struct btd_adapter *adapter;
- struct bonding_request_info *bonding;
struct btd_device *device;
adapter = manager_find_adapter(local);
@@ -1166,42 +958,32 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle,
ba2str(peer, peer_addr);
device = adapter_get_device(connection, adapter, peer_addr);
+ if (!device) {
+ error("No matching device found");
+ return;
+ }
if (status) {
- struct pending_auth_info *auth;
-
- auth = adapter_find_auth_request(adapter, peer);
- if (auth && auth->agent)
- agent_cancel(auth->agent);
-
- adapter_remove_auth_request(adapter, peer);
-
- if (device)
- device_set_secmode3_conn(device, FALSE);
+ device_set_secmode3_conn(device, FALSE);
+ if (device_is_bonding(device, NULL))
+ device_bonding_complete(device, status);
+ return;
+ }
- bonding = adapter_get_bonding_info(adapter);
- if (bonding)
- bonding->hci_status = status;
- } else {
- if (device)
- device_set_connected(connection, device, TRUE);
+ device_set_connected(device, connection, TRUE);
- /* add in the active connetions list */
- adapter_add_active_conn(adapter, peer, handle);
- }
+ /* add in the active connetions list */
+ adapter_add_active_conn(adapter, peer, handle);
}
void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status,
uint16_t handle, uint8_t reason)
{
- DBusMessage *reply;
char peer_addr[18];
struct btd_adapter *adapter;
struct btd_device *device;
struct active_conn_info *dev;
- struct pending_auth_info *auth;
uint16_t dev_id;
- struct bonding_request_info *bonding;
if (status) {
error("Disconnection failed: 0x%02x", status);
@@ -1227,39 +1009,17 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status,
/* clean pending HCI cmds */
hci_req_queue_remove(dev_id, &dev->bdaddr);
- /* Cancel D-Bus/non D-Bus requests */
- auth = adapter_find_auth_request(adapter, &dev->bdaddr);
- if (auth && auth->agent)
- agent_cancel(auth->agent);
-
- adapter_remove_auth_request(adapter, &dev->bdaddr);
-
- bonding = adapter_get_bonding_info(adapter);
- /* Check if there is a pending Bonding request */
- if (bonding && (bacmp(&bonding->bdaddr, &dev->bdaddr) == 0)) {
- if (bonding->cancel) {
- /* reply authentication canceled */
- reply = new_authentication_return(bonding->msg,
- HCI_OE_USER_ENDED_CONNECTION);
- g_dbus_send_message(connection, reply);
- } else {
- reply = new_authentication_return(bonding->msg,
- HCI_AUTHENTICATION_FAILURE);
- g_dbus_send_message(connection, reply);
- }
- adapter_free_bonding_request(adapter);
- }
-
adapter_remove_active_conn(adapter, dev);
device = adapter_find_device(adapter, peer_addr);
- if (device) {
- device_set_connected(connection, device, FALSE);
+ if (!device)
+ return;
- if (device_is_temporary(device)) {
- debug("Removing temporary device %s", peer_addr);
- adapter_remove_device(connection, adapter, device);
- }
+ device_set_connected(device, connection, FALSE);
+
+ if (device_is_temporary(device)) {
+ debug("Removing temporary device %s", peer_addr);
+ adapter_remove_device(connection, adapter, device);
}
}
@@ -1482,14 +1242,16 @@ int hcid_dbus_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
if (get_auth_requirements(local, remote, auth) < 0)
return -1;
- if (!adapter_pairing_initiator(adapter, remote) &&
- !adapter_is_pairable(adapter))
- return -EPERM;
-
ba2str(remote, addr);
- /* For CreatePairedDevice use dedicated bonding */
device = adapter_find_device(adapter, addr);
+ /* Check if the adapter is not pairable and if there isn't a bonding in
+ * progress */
+ if (!adapter_is_pairable(adapter) &&
+ !(device && device_is_bonding(device, NULL)))
+ return -EPERM;
+
+ /* For CreatePairedDevice use dedicated bonding */
if (device) {
agent = device_get_agent(device);
if (agent)
diff --git a/src/device.c b/src/device.c
index f51184ca..7891d1e5 100644
--- a/src/device.c
+++ b/src/device.c
@@ -35,6 +35,7 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
+#include <bluetooth/l2cap.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
@@ -65,6 +66,22 @@ struct btd_driver_data {
void *priv;
};
+struct bonding_req {
+ DBusConnection *conn;
+ DBusMessage *msg;
+ GIOChannel *io;
+ guint io_id;
+ guint listener_id;
+ struct btd_device *device;
+};
+
+struct authentication_req {
+ auth_type_t type;
+ void *cb;
+ struct agent *agent;
+ struct btd_device *device;
+};
+
struct btd_device {
bdaddr_t bdaddr;
gchar *path;
@@ -78,6 +95,8 @@ struct btd_device {
char *discov_requestor; /* discovery requestor unique name */
guint discov_listener;
guint discov_timer;
+ struct bonding_req *bonding;
+ struct authentication_req *authr; /* authentication request */
/* For Secure Simple Pairing */
uint8_t cap;
@@ -111,6 +130,39 @@ static uint16_t uuid_list[] = {
static GSList *device_drivers = NULL;
+static DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn,
+ DBusMessage *msg, int err)
+{
+ return error_common_reply(conn, msg,
+ ERROR_INTERFACE ".ConnectionAttemptFailed",
+ err > 0 ? strerror(err) : "Connection attempt failed");
+}
+
+static DBusHandlerResult error_failed(DBusConnection *conn,
+ DBusMessage *msg, const char * desc)
+{
+ return error_common_reply(conn, msg, ERROR_INTERFACE ".Failed", desc);
+}
+
+static DBusHandlerResult error_failed_errno(DBusConnection *conn,
+ DBusMessage *msg, int err)
+{
+ const char *desc = strerror(err);
+
+ return error_failed(conn, msg, desc);
+}
+
+static inline DBusMessage *no_such_adapter(DBusMessage *msg)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchAdapter",
+ "No such adapter");
+}
+
+static inline DBusMessage *in_progress(DBusMessage *msg, const char *str)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress", str);
+}
+
static void device_free(gpointer user_data)
{
struct btd_device *device = user_data;
@@ -254,13 +306,6 @@ static DBusMessage *get_properties(DBusConnection *conn,
ptr = adapter_get_path(adapter);
dict_append_entry(&dict, "Adapter", DBUS_TYPE_OBJECT_PATH, &ptr);
- if (read_remote_eir(&src, &device->bdaddr, NULL) < 0)
- boolean = TRUE;
- else
- boolean = FALSE;
-
- dict_append_entry(&dict, "LegacyPairing", DBUS_TYPE_BOOLEAN, &boolean);
-
dbus_message_iter_close_container(&iter, &dict);
return reply;
@@ -523,7 +568,7 @@ gboolean device_get_connected(struct btd_device *device)
return device->connected;
}
-void device_set_connected(DBusConnection *conn, struct btd_device *device,
+void device_set_connected(struct btd_device *device, DBusConnection *conn,
gboolean connected)
{
device->connected = connected;
@@ -579,7 +624,61 @@ struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapt
return device;
}
-void device_remove(DBusConnection *conn, struct btd_device *device)
+static void device_remove_bonding(struct btd_device *device, DBusConnection *conn)
+{
+ struct active_conn_info *ci;
+ char filename[PATH_MAX + 1];
+ char *str, srcaddr[18], dstaddr[18];
+ int dd, dev_id;
+ bdaddr_t bdaddr;
+ gboolean paired;
+
+ adapter_get_address(device->adapter, &bdaddr);
+ ba2str(&bdaddr, srcaddr);
+ ba2str(&device->bdaddr, dstaddr);
+
+ dev_id = adapter_get_dev_id(device->adapter);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0)
+ return;
+
+ create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
+ "linkkeys");
+
+ /* textfile_del doesn't return an error when the key is not found */
+ str = textfile_caseget(filename, dstaddr);
+ paired = str ? TRUE : FALSE;
+ g_free(str);
+
+ if (!paired)
+ return;
+
+ /* Delete the link key from storage */
+ textfile_casedel(filename, dstaddr);
+
+ /* Delete the link key from the Bluetooth chip */
+ hci_delete_stored_link_key(dd, &device->bdaddr, 0, HCI_REQ_TIMEOUT);
+
+ /* Send the HCI disconnect command */
+ ci = adapter_search_active_conn_by_bdaddr(device->adapter,
+ &device->bdaddr);
+ if (ci) {
+ int err = hci_disconnect(dd, htobs(ci->handle),
+ HCI_OE_USER_ENDED_CONNECTION,
+ HCI_REQ_TIMEOUT);
+ if (err < 0)
+ error("Disconnect: %s (%d)", strerror(-err), -err);
+ }
+
+ hci_close_dev(dd);
+
+ paired = FALSE;
+ emit_property_changed(conn, device->path, DEVICE_INTERFACE,
+ "Paired", DBUS_TYPE_BOOLEAN, &paired);
+}
+
+void device_remove(struct btd_device *device, DBusConnection *conn)
{
GSList *list;
struct btd_device_driver *driver;
@@ -587,6 +686,12 @@ void device_remove(DBusConnection *conn, struct btd_device *device)
debug("Removing device %s", path);
+ if (device->bonding)
+ device_cancel_bonding(device, HCI_OE_USER_ENDED_CONNECTION);
+
+ if (!device->temporary)
+ device_remove_bonding(device, conn);
+
for (list = device->drivers; list; list = list->next) {
struct btd_driver_data *driver_data = list->data;
driver = driver_data->driver;
@@ -1280,15 +1385,356 @@ static gboolean start_discovery(gpointer user_data)
return FALSE;
}
-int device_set_paired(DBusConnection *conn, struct btd_device *device,
- struct bonding_request_info *bonding)
+DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
{
- dbus_bool_t paired = TRUE;
+ switch (status) {
+ case 0x00: /* success */
+ return dbus_message_new_method_return(msg);
+
+ case 0x04: /* page timeout */
+ case 0x08: /* connection timeout */
+ case 0x10: /* connection accept timeout */
+ case 0x22: /* LMP response timeout */
+ case 0x28: /* instant passed - is this a timeout? */
+ return dbus_message_new_error(msg,
+ ERROR_INTERFACE ".AuthenticationTimeout",
+ "Authentication Timeout");
+ case 0x17: /* too frequent pairing attempts */
+ return dbus_message_new_error(msg,
+ ERROR_INTERFACE ".RepeatedAttempts",
+ "Repeated Attempts");
+
+ case 0x06:
+ case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */
+ return dbus_message_new_error(msg,
+ ERROR_INTERFACE ".AuthenticationRejected",
+ "Authentication Rejected");
+
+ case 0x07: /* memory capacity */
+ case 0x09: /* connection limit */
+ case 0x0a: /* synchronous connection limit */
+ case 0x0d: /* limited resources */
+ case 0x13: /* user ended the connection */
+ case 0x14: /* terminated due to low resources */
+ return dbus_message_new_error(msg,
+ ERROR_INTERFACE ".AuthenticationCanceled",
+ "Authentication Canceled");
+
+ case 0x05: /* authentication failure */
+ case 0x0E: /* rejected due to security reasons - is this auth failure? */
+ case 0x25: /* encryption mode not acceptable - is this auth failure? */
+ case 0x26: /* link key cannot be changed - is this auth failure? */
+ case 0x29: /* pairing with unit key unsupported - is this auth failure? */
+ case 0x2f: /* insufficient security - is this auth failure? */
+ default:
+ return dbus_message_new_error(msg,
+ ERROR_INTERFACE ".AuthenticationFailed",
+ "Authentication Failed");
+ }
+}
+
+static void bonding_request_free(struct bonding_req *bonding)
+{
+ struct btd_device *device;
+
+ if (!bonding)
+ return;
+
+ if (bonding->listener_id)
+ g_dbus_remove_watch(bonding->conn, bonding->listener_id);
- device_set_temporary(device, FALSE);
+ if (bonding->msg)
+ dbus_message_unref(bonding->msg);
+
+ if (bonding->conn)
+ dbus_connection_unref(bonding->conn);
+
+ if (bonding->io_id)
+ g_source_remove(bonding->io_id);
+
+ if (bonding->io)
+ g_io_channel_unref(bonding->io);
+
+ device = bonding->device;
+
+ if (device && device->agent) {
+ agent_destroy(device->agent, FALSE);
+ device->agent = NULL;
+ }
+
+ device->bonding = NULL;
+ g_free(bonding);
+}
+
+static void device_set_paired(struct btd_device *device, gboolean value)
+{
+ DBusConnection *conn = get_dbus_connection();
emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Paired",
- DBUS_TYPE_BOOLEAN, &paired);
+ DBUS_TYPE_BOOLEAN, &value);
+}
+
+static void device_agent_removed(struct agent *agent, void *user_data)
+{
+ struct btd_device *device = user_data;
+
+ device_set_agent(device, NULL);
+
+ if (device->authr)
+ device->authr->agent = NULL;
+}
+
+static struct bonding_req *bonding_request_new(DBusConnection *conn,
+ DBusMessage *msg,
+ struct btd_device *device,
+ const char *agent_path,
+ uint8_t capability)
+{
+ struct bonding_req *bonding;
+ const char *name = dbus_message_get_sender(msg);
+ struct agent *agent;
+
+ debug("%s: requesting bonding", device->path);
+
+ if (!agent_path)
+ goto proceed;
+
+ agent = agent_create(device->adapter, name, agent_path,
+ capability,
+ device_agent_removed,
+ device);
+ if (!agent) {
+ error("Unable to create a new agent");
+ return NULL;
+ }
+
+ device->agent = agent;
+
+ debug("Temporary agent registered for %s at %s:%s",
+ device->path, name, agent_path);
+
+proceed:
+
+ bonding = g_new0(struct bonding_req, 1);
+
+ bonding->conn = dbus_connection_ref(conn);
+ bonding->msg = dbus_message_ref(msg);
+
+ return bonding;
+}
+
+static gboolean create_bonding_io_cb(GIOChannel *io, GIOCondition cond,
+ struct btd_device *device)
+{
+ struct hci_request rq;
+ auth_requested_cp cp;
+ evt_cmd_status rp;
+ struct l2cap_conninfo cinfo;
+ socklen_t len;
+ int sk, dd, ret;
+
+ if (!device->bonding) {
+ /* If we come here it implies a bug somewhere */
+ debug("create_bonding_io_cb: no pending bonding!");
+ g_io_channel_close(io);
+ return FALSE;
+ }
+
+ if (cond & G_IO_NVAL) {
+ if (device->bonding) {
+ DBusMessage *reply;
+
+ reply = new_authentication_return(device->bonding->msg,
+ 0x09);
+ g_dbus_send_message(device->bonding->conn, reply);
+ }
+
+ goto cleanup;
+ }
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ debug("Hangup or error on bonding IO channel");
+
+ if (device->bonding)
+ error_connection_attempt_failed(device->bonding->conn,
+ device->bonding->msg,
+ ENETDOWN);
+
+ goto failed;
+ }
+
+ sk = g_io_channel_unix_get_fd(io);
+
+ len = sizeof(ret);
+ if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
+ error("Can't get socket error: %s (%d)",
+ strerror(errno), errno);
+ error_failed_errno(device->bonding->conn, device->bonding->msg,
+ errno);
+ goto failed;
+ }
+
+ if (ret != 0) {
+ if (device->bonding)
+ error_connection_attempt_failed(device->bonding->conn,
+ device->bonding->msg,
+ ret);
+ goto failed;
+ }
+
+ len = sizeof(cinfo);
+ if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) {
+ error("Can't get connection info: %s (%d)",
+ strerror(errno), errno);
+ error_failed_errno(device->bonding->conn, device->bonding->msg,
+ errno);
+ goto failed;
+ }
+
+ dd = hci_open_dev(adapter_get_dev_id(device->adapter));
+ if (dd < 0) {
+ DBusMessage *reply = no_such_adapter(device->bonding->msg);
+ g_dbus_send_message(device->bonding->conn, reply);
+ goto failed;
+ }
+
+ memset(&rp, 0, sizeof(rp));
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = htobs(cinfo.hci_handle);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LINK_CTL;
+ rq.ocf = OCF_AUTH_REQUESTED;
+ rq.cparam = &cp;
+ rq.clen = AUTH_REQUESTED_CP_SIZE;
+ rq.rparam = &rp;
+ rq.rlen = EVT_CMD_STATUS_SIZE;
+ rq.event = EVT_CMD_STATUS;
+
+ if (hci_send_req(dd, &rq, HCI_REQ_TIMEOUT) < 0) {
+ error("Unable to send HCI request: %s (%d)",
+ strerror(errno), errno);
+ error_failed_errno(device->bonding->conn, device->bonding->msg,
+ errno);
+ hci_close_dev(dd);
+ goto failed;
+ }
+
+ if (rp.status) {
+ error("HCI_Authentication_Requested failed with status 0x%02x",
+ rp.status);
+ error_failed_errno(device->bonding->conn, device->bonding->msg,
+ bt_error(rp.status));
+ hci_close_dev(dd);
+ goto failed;
+ }
+
+ hci_close_dev(dd);
+
+ device->bonding->io_id = g_io_add_watch(io,
+ G_IO_NVAL | G_IO_HUP | G_IO_ERR,
+ (GIOFunc) create_bonding_io_cb,
+ device);
+
+ return FALSE;
+
+failed:
+ g_io_channel_close(io);
+
+cleanup:
+ device->bonding->io_id = 0;
+ bonding_request_free(device->bonding);
+
+ return FALSE;
+}
+
+static void create_bond_req_exit(DBusConnection *conn, void *user_data)
+{
+ struct btd_device *device = user_data;
+
+ debug("%s: requestor exited before bonding was completed", device->path);
+
+ if (device->authr)
+ device_cancel_authentication(device);
+
+ if (device->bonding) {
+ device->bonding->listener_id = 0;
+ g_io_channel_close(device->bonding->io);
+ bonding_request_free(device->bonding);
+ }
+}
+
+DBusMessage *device_create_bonding(struct btd_device *device,
+ DBusConnection *conn,
+ DBusMessage *msg,
+ const char *agent_path,
+ uint8_t capability)
+{
+ char filename[PATH_MAX + 1];
+ char *str, srcaddr[18], dstaddr[18];
+ struct btd_adapter *adapter = device->adapter;
+ struct bonding_req *bonding;
+ bdaddr_t src;
+ int sk;
+
+ adapter_get_address(adapter, &src);
+ ba2str(&src, srcaddr);
+ ba2str(&device->bdaddr, dstaddr);
+
+ if (device->bonding)
+ return in_progress(msg, "Bonding in progress");
+
+ /* check if a link key already exists */
+ create_name(filename, PATH_MAX, STORAGEDIR, srcaddr,
+ "linkkeys");
+
+ str = textfile_caseget(filename, dstaddr);
+ if (str) {
+ free(str);
+ return g_dbus_create_error(msg,
+ ERROR_INTERFACE ".AlreadyExists",
+ "Bonding already exists");
+ }
+
+ sk = l2raw_connect(&src, &device->bdaddr);
+ if (sk < 0)
+ return g_dbus_create_error(msg,
+ ERROR_INTERFACE ".ConnectionAttemptFailed",
+ "Connection attempt failed");
+
+ bonding = bonding_request_new(conn, msg, device, agent_path,
+ capability);
+ if (!bonding) {
+ close(sk);
+ return NULL;
+ }
+
+ bonding->io = g_io_channel_unix_new(sk);
+ bonding->io_id = g_io_add_watch(bonding->io,
+ G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
+ (GIOFunc) create_bonding_io_cb,
+ device);
+
+ bonding->listener_id = g_dbus_add_disconnect_watch(conn,
+ dbus_message_get_sender(msg),
+ create_bond_req_exit, device,
+ NULL);
+
+ device->bonding = bonding;
+ bonding->device = device;
+
+ return NULL;
+}
+
+void device_bonding_complete(struct btd_device *device, uint8_t status)
+{
+ struct bonding_req *bonding = device->bonding;
+
+ if (status)
+ goto failed;
+
+ device->temporary = FALSE;
/* If we were initiators start service discovery immediately.
* However if the other end was the initator wait a few seconds
@@ -1302,18 +1748,218 @@ int device_set_paired(DBusConnection *conn, struct btd_device *device,
device->discov_timer = 0;
}
- return device_browse(device, bonding->conn, bonding->msg,
- NULL, FALSE);
+ device_browse(device, bonding->conn, bonding->msg,
+ NULL, FALSE);
+ } else if (!device->discov_active && !device->discov_timer) {
+ /* If we are not initiators and there is no currently active
+ * discovery or discovery timer, set the discovery timer */
+ device->discov_timer = g_timeout_add_seconds(DISCOVERY_TIMER,
+ start_discovery,
+ device);
}
- /* If we are not initiators and there is no currently active discovery
- * or discovery timer, set the discovery timer */
- if (!device->discov_active && !device->discov_timer)
- device->discov_timer = g_timeout_add_seconds(DISCOVERY_TIMER,
- start_discovery,
- device);
+ device_set_paired(device, TRUE);
- return 0;
+ g_free(device->authr);
+ device->authr = NULL;
+ bonding_request_free(bonding);
+
+ return;
+
+failed:
+
+ device_cancel_bonding(device, status);
+}
+
+gboolean device_is_bonding(struct btd_device *device, const char *sender)
+{
+ struct bonding_req *bonding = device->bonding;
+
+ if (!device->bonding)
+ return FALSE;
+
+ if (!sender)
+ return TRUE;
+
+ return g_str_equal(sender, dbus_message_get_sender(bonding->msg));
+}
+
+void device_cancel_bonding(struct btd_device *device, uint8_t status)
+{
+ struct bonding_req *bonding = device->bonding;
+ DBusMessage *reply;
+
+ if (!bonding)
+ return;
+
+ debug("%s: canceling bonding request", device->path);
+
+ if (device->authr)
+ device_cancel_authentication(device);
+
+ reply = new_authentication_return(bonding->msg, status);
+ g_dbus_send_message(bonding->conn, reply);
+
+ if (device->bonding->io_id)
+ g_source_remove(device->bonding->io_id);
+
+ bonding_request_free(bonding);
+}
+
+static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,
+ void *data)
+{
+ struct authentication_req *auth = data;
+ struct btd_device *device = auth->device;
+
+ /* No need to reply anything if the authentication already failed */
+ if (!auth->cb)
+ return;
+
+ ((agent_pincode_cb) auth->cb)(agent, err, pincode, device);
+
+ auth->cb = NULL;
+}
+
+static void confirm_cb(struct agent *agent, DBusError *err, void *data)
+{
+ struct authentication_req *auth = data;
+ struct btd_device *device = auth->device;
+
+ /* No need to reply anything if the authentication already failed */
+ if (!auth->cb)
+ return;
+
+ ((agent_cb) auth->cb)(agent, err, device);
+
+ auth->cb = NULL;
+}
+
+static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
+ void *data)
+{
+ struct authentication_req *auth = data;
+ struct btd_device *device = auth->device;
+
+ /* No need to reply anything if the authentication already failed */
+ if (!auth->cb)
+ return;
+
+ ((agent_passkey_cb) auth->cb)(agent, err, passkey, device);
+
+ auth->cb = NULL;
+}
+
+int device_request_authentication(struct btd_device *device, auth_type_t type,
+ uint32_t passkey, void *cb)
+{
+ struct authentication_req *auth;
+ struct agent *agent;
+ int ret;
+
+ debug("%s: requesting agent authentication", device->path);
+
+ agent = device->agent;
+
+ if (!agent)
+ agent = adapter_get_agent(device->adapter);
+
+ if (!agent) {
+ error("No agent available for %u request", type);
+ return -EPERM;
+ }
+
+ auth = g_new0(struct authentication_req, 1);
+ auth->agent = agent;
+ auth->device = device;
+ auth->cb = cb;
+ auth->type = type;
+ device->authr = auth;
+
+ switch (type) {
+ case AUTH_TYPE_PINCODE:
+ ret = agent_request_pincode(agent, device, pincode_cb,
+ auth);
+ break;
+ case AUTH_TYPE_PASSKEY:
+ ret = agent_request_passkey(agent, device, passkey_cb,
+ auth);
+ break;
+ case AUTH_TYPE_CONFIRM:
+ ret = agent_request_confirmation(agent, device, passkey,
+ confirm_cb, auth);
+ break;
+ case AUTH_TYPE_NOTIFY:
+ ret = agent_display_passkey(agent, device, passkey);
+ break;
+ case AUTH_TYPE_AUTO:
+ ret = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret < 0) {
+ error("Failed requesting authentication");
+ g_free(auth);
+ device->authr = NULL;
+ }
+
+ return ret;
+}
+
+static void cancel_authentication(struct authentication_req *auth)
+{
+ struct btd_device *device = auth->device;
+ struct agent *agent = auth->agent;
+ DBusError err;
+
+ if (!auth->cb)
+ return;
+
+ dbus_error_init(&err);
+ dbus_set_error_const(&err, "org.bluez.Error.Canceled", NULL);
+
+ switch (auth->type) {
+ case AUTH_TYPE_PINCODE:
+ ((agent_pincode_cb) auth->cb)(agent, &err, NULL, device);
+ break;
+ case AUTH_TYPE_CONFIRM:
+ ((agent_cb) auth->cb)(agent, &err, device);
+ break;
+ case AUTH_TYPE_PASSKEY:
+ ((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
+ break;
+ case AUTH_TYPE_NOTIFY:
+ case AUTH_TYPE_AUTO:
+ /* User Notify/Auto doesn't require any reply */
+ break;
+ }
+
+ dbus_error_free(&err);
+ auth->cb = NULL;
+}
+
+void device_cancel_authentication(struct btd_device *device)
+{
+ struct authentication_req *auth = device->authr;
+
+ if (!auth)
+ return;
+
+ debug("%s: canceling authentication request", device->path);
+
+ if (auth->agent)
+ agent_cancel(auth->agent);
+
+ cancel_authentication(auth);
+ device->authr = NULL;
+ g_free(auth);
+}
+
+gboolean device_is_authenticating(struct btd_device *device)
+{
+ return (device->authr != NULL);
}
void btd_device_add_uuid(struct btd_device *device, const char *uuid)
diff --git a/src/device.h b/src/device.h
index 4113ecdb..c9137f7c 100644
--- a/src/device.h
+++ b/src/device.h
@@ -24,9 +24,19 @@
#define DEVICE_INTERFACE "org.bluez.Device"
+struct btd_device;
+
+typedef enum {
+ AUTH_TYPE_PINCODE,
+ AUTH_TYPE_PASSKEY,
+ AUTH_TYPE_CONFIRM,
+ AUTH_TYPE_NOTIFY,
+ AUTH_TYPE_AUTO,
+} auth_type_t;
+
struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
const gchar *address);
-void device_remove(DBusConnection *conn, struct btd_device *device);
+void device_remove(struct btd_device *device, DBusConnection *conn);
gint device_address_cmp(struct btd_device *device, const gchar *address);
int device_browse(struct btd_device *device, DBusConnection *conn,
DBusMessage *msg, uuid_t *search, gboolean reverse);
@@ -45,12 +55,21 @@ void device_set_temporary(struct btd_device *device, gboolean temporary);
void device_set_cap(struct btd_device *device, uint8_t cap);
void device_set_auth(struct btd_device *device, uint8_t auth);
uint8_t device_get_auth(struct btd_device *device);
-int device_set_paired(DBusConnection *conn, struct btd_device *device,
- struct bonding_request_info *bonding);
gboolean device_get_connected(struct btd_device *device);
-void device_set_connected(DBusConnection *conn, struct btd_device *device,
+void device_set_connected(struct btd_device *device, DBusConnection *conn,
gboolean connected);
void device_set_secmode3_conn(struct btd_device *device, gboolean enable);
+DBusMessage *device_create_bonding(struct btd_device *device,
+ DBusConnection *conn, DBusMessage *msg,
+ const char *agent_path, uint8_t capability);
+void device_remove_bondind(struct btd_device *device, DBusConnection *connection);
+void device_bonding_complete(struct btd_device *device, uint8_t status);
+gboolean device_is_bonding(struct btd_device *device, const char *sender);
+void device_cancel_bonding(struct btd_device *device, uint8_t status);
+int device_request_authentication(struct btd_device *device, auth_type_t type,
+ uint32_t passkey, void *cb);
+void device_cancel_authentication(struct btd_device *device);
+gboolean device_is_authenticating(struct btd_device *device);
#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } )