summaryrefslogtreecommitdiffstats
path: root/hcid/adapter.c
diff options
context:
space:
mode:
Diffstat (limited to 'hcid/adapter.c')
-rw-r--r--hcid/adapter.c113
1 files changed, 94 insertions, 19 deletions
diff --git a/hcid/adapter.c b/hcid/adapter.c
index 1383ed50..9c70b0e9 100644
--- a/hcid/adapter.c
+++ b/hcid/adapter.c
@@ -59,6 +59,8 @@
#include "dbus-hci.h"
#include "dbus-sdp.h"
#include "dbus-database.h"
+#include "dbus-service.h"
+#include "dbus-security.h"
#include "dbus-error.h"
#include "error.h"
#include "glib-helper.h"
@@ -2574,9 +2576,7 @@ failed:
remove_pending_device(adapter);
cleanup:
- name_listener_remove(adapter->bonding->conn,
- dbus_message_get_sender(adapter->bonding->msg),
- (name_cb_t) create_bond_req_exit, adapter);
+ name_listener_id_remove(adapter->bonding->listener_id);
bonding_request_free(adapter->bonding);
adapter->bonding = NULL;
@@ -2584,6 +2584,51 @@ cleanup:
return FALSE;
}
+static void create_bond_req_exit(const char *name, void *user_data)
+{
+ struct adapter *adapter = user_data;
+ char path[MAX_PATH_LENGTH];
+ GSList *l;
+
+ snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, adapter->dev_id);
+
+ debug("CreateConnection requestor (%s) exited before bonding was completed",
+ name);
+
+ cancel_passkey_agent_requests(adapter->passkey_agents, path,
+ &adapter->bonding->bdaddr);
+ release_passkey_agents(adapter, &adapter->bonding->bdaddr);
+
+ l = g_slist_find_custom(adapter->pin_reqs, &adapter->bonding->bdaddr,
+ pin_req_cmp);
+ if (l) {
+ struct pending_pin_info *p = l->data;
+
+ if (!p->replied) {
+ int dd;
+
+ dd = hci_open_dev(adapter->dev_id);
+ if (dd >= 0) {
+ hci_send_cmd(dd, OGF_LINK_CTL,
+ OCF_PIN_CODE_NEG_REPLY,
+ 6, &adapter->bonding->bdaddr);
+ hci_close_dev(dd);
+ }
+ }
+
+ adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, p);
+ g_free(p);
+ }
+
+ remove_pending_device(adapter);
+
+ g_io_channel_close(adapter->bonding->io);
+ if (adapter->bonding->io_id)
+ g_source_remove(adapter->bonding->io_id);
+ bonding_request_free(adapter->bonding);
+ adapter->bonding = NULL;
+}
+
static DBusHandlerResult create_bonding(DBusConnection *conn, DBusMessage *msg,
const char *address, const char *agent_path,
void *data)
@@ -2591,6 +2636,7 @@ static DBusHandlerResult create_bonding(DBusConnection *conn, DBusMessage *msg,
char filename[PATH_MAX + 1];
char *str;
struct adapter *adapter = data;
+ struct bonding_request_info *bonding;
bdaddr_t bdaddr;
int sk;
@@ -2622,21 +2668,23 @@ static DBusHandlerResult create_bonding(DBusConnection *conn, DBusMessage *msg,
if (sk < 0)
return error_connection_attempt_failed(conn, msg, 0);
- adapter->bonding = bonding_request_new(conn, msg, adapter, address,
- agent_path);
- if (!adapter->bonding) {
+ bonding = bonding_request_new(conn, msg, adapter, address, agent_path);
+ if (!bonding) {
close(sk);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
- adapter->bonding->io = g_io_channel_unix_new(sk);
- adapter->bonding->io_id = g_io_add_watch(adapter->bonding->io,
- G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
- (GIOFunc) create_bonding_conn_complete,
- adapter);
+ 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_conn_complete,
+ adapter);
+
+ bonding->listener_id = name_listener_add(conn,
+ dbus_message_get_sender(msg),
+ create_bond_req_exit, adapter);
- name_listener_add(conn, dbus_message_get_sender(msg),
- (name_cb_t) create_bond_req_exit, adapter);
+ adapter->bonding = bonding;
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -2892,6 +2940,19 @@ static DBusHandlerResult adapter_get_encryption_key_size(DBusConnection *conn,
return send_message_and_unref(conn, reply);
}
+static void periodic_discover_req_exit(const char *name, void *user_data)
+{
+ struct adapter *adapter = user_data;
+
+ debug("PeriodicDiscovery requestor (%s) exited", name);
+
+ /* Cleanup the discovered devices list and send the cmd to exit from
+ * periodic inquiry or cancel remote name request. The return value can
+ * be ignored. */
+
+ cancel_periodic_discovery(adapter);
+}
+
static DBusHandlerResult adapter_start_periodic(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -2966,9 +3027,10 @@ static DBusHandlerResult adapter_start_periodic(DBusConnection *conn,
/* track the request owner to cancel it automatically if the owner
* exits */
- name_listener_add(conn, dbus_message_get_sender(msg),
- (name_cb_t) periodic_discover_req_exit,
- adapter);
+ adapter->pdiscov_listener = name_listener_add(conn,
+ dbus_message_get_sender(msg),
+ periodic_discover_req_exit,
+ adapter);
return send_message_and_unref(conn, reply);
}
@@ -3079,6 +3141,17 @@ static DBusHandlerResult adapter_get_pdiscov_resolve(DBusConnection *conn,
return send_message_and_unref(conn, reply);
}
+static void discover_devices_req_exit(const char *name, void *user_data)
+{
+ struct adapter *adapter = user_data;
+
+ debug("DiscoverDevices requestor (%s) exited", name);
+
+ /* Cleanup the discovered devices list and send the command to cancel
+ * inquiry or cancel remote name request. The return can be ignored. */
+ cancel_discovery(adapter);
+}
+
static DBusHandlerResult adapter_discover_devices(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -3152,8 +3225,10 @@ static DBusHandlerResult adapter_discover_devices(DBusConnection *conn,
/* track the request owner to cancel it automatically if the owner
* exits */
- name_listener_add(conn, dbus_message_get_sender(msg),
- (name_cb_t) discover_devices_req_exit, adapter);
+ adapter->discov_listener = name_listener_add(conn,
+ dbus_message_get_sender(msg),
+ discover_devices_req_exit,
+ adapter);
return send_message_and_unref(conn, reply);
}
@@ -3692,7 +3767,7 @@ static DBusHandlerResult request_mode(DBusConnection *conn,
req->msg = dbus_message_ref(msg);
req->mode = new_mode;
req->id = name_listener_add(conn, dbus_message_get_sender(msg),
- (name_cb_t) session_exit, req);
+ session_exit, req);
if (!adapter->sessions)
adapter->global_mode = adapter->mode;