summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2006-08-19 01:24:47 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2006-08-19 01:24:47 +0000
commitf841e8de8c71a0f726f77a65b4145b76e924df14 (patch)
tree1c01979716966d1e0cf0066df8fa4caae7086bd0
parent9f1c935d4e9a36ad0af6afb0b0e9893397698efa (diff)
Improve situation where bonding requestor exits
-rw-r--r--hcid/dbus.c29
-rw-r--r--hcid/security.c82
2 files changed, 77 insertions, 34 deletions
diff --git a/hcid/dbus.c b/hcid/dbus.c
index 7f72d7cc..ec79a932 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -1980,7 +1980,34 @@ void create_bond_req_exit(const char *name, struct hci_dbus_data *pdata)
snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, pdata->dev_id);
- debug("PasskeyAgent at %s exited before bonding was completed", name);
+ debug("CreateConnection requestor at %s exited before bonding was completed", name);
cancel_passkey_agent_requests(pdata->passkey_agents, path, &pdata->bonding->bdaddr);
+
+ if (pdata->bonding->disconnect) {
+ struct slist *l;
+
+ l = slist_find(pdata->active_conn, &pdata->bonding->bdaddr, active_conn_find_by_bdaddr);
+ if (l) {
+ struct active_conn_info *con = l->data;
+ struct hci_req_data *data;
+ disconnect_cp cp;
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = con->handle;
+ cp.reason = HCI_OE_USER_ENDED_CONNECTION;
+
+ data = hci_req_data_new(pdata->dev_id, &pdata->bonding->bdaddr, OGF_LINK_CTL,
+ OCF_DISCONNECT, EVT_DISCONN_COMPLETE,
+ &cp, DISCONNECT_CP_SIZE);
+
+ hci_req_queue_append(data);
+ }
+ }
+
+ bonding_request_free(pdata->bonding);
+ pdata->bonding = NULL;
+
+ free(pdata->requestor_name);
+ pdata->requestor_name = NULL;
}
diff --git a/hcid/security.c b/hcid/security.c
index 32172e63..9b02f213 100644
--- a/hcid/security.c
+++ b/hcid/security.c
@@ -94,9 +94,57 @@ struct hci_req_data *hci_req_data_new(int dev_id, const bdaddr_t *dba, uint16_t
return data;
}
+static int hci_req_find_by_devid(const void *data, const void *user_data)
+{
+ const struct hci_req_data *req = data;
+ const int *dev_id = user_data;
+
+ return (*dev_id - req->dev_id);
+}
+
+static void hci_req_queue_process(int dev_id)
+{
+ int dd, ret_val;
+
+ /* send the next pending cmd */
+ dd = hci_open_dev(dev_id);
+ do {
+ struct hci_req_data *data;
+ struct slist *l = slist_find(hci_req_queue, &dev_id, hci_req_find_by_devid);
+
+ if (!l)
+ break;
+
+ data = l->data;
+ data->status = REQ_SENT;
+
+ ret_val = hci_send_cmd(dd, data->ogf, data->ocf, data->clen, data->cparam);
+ if (ret_val < 0) {
+ hci_req_queue = slist_remove(hci_req_queue, data);
+ free(data->cparam);
+ free(data);
+ }
+
+ } while(ret_val < 0);
+
+ hci_close_dev(dd);
+}
+
void hci_req_queue_append(struct hci_req_data *data)
{
+ struct slist *l;
+ struct hci_req_data *match;
+
+
hci_req_queue = slist_append(hci_req_queue, data);
+
+ l = slist_find(hci_req_queue, &data->dev_id, hci_req_find_by_devid);
+ match = l->data;
+
+ if (match->status == REQ_SENT)
+ return;
+
+ hci_req_queue_process(data->dev_id);
}
void hci_req_queue_remove(int dev_id, bdaddr_t *dba)
@@ -116,19 +164,10 @@ void hci_req_queue_remove(int dev_id, bdaddr_t *dba)
}
}
-static int hci_req_find_by_devid(const void *data, const void *user_data)
-{
- const struct hci_req_data *req = data;
- const int *dev_id = user_data;
-
- return (*dev_id - req->dev_id);
-}
-
static void check_pending_hci_req(int dev_id, int event)
{
struct hci_req_data *data;
struct slist *l;
- int dd, ret_val;
if (!hci_req_queue)
return;
@@ -152,30 +191,7 @@ static void check_pending_hci_req(int dev_id, int event)
free(data);
}
- /* send the next pending cmd */
- dd = hci_open_dev(dev_id);
- do {
- l = slist_find(hci_req_queue, &dev_id, hci_req_find_by_devid);
-
- if (!l)
- goto failed;
-
- data = l->data;
- data->status = REQ_SENT;
-
- ret_val = hci_send_cmd(dd, data->ogf, data->ocf, data->clen, data->cparam);
- if (ret_val < 0) {
- hci_req_queue = slist_remove(hci_req_queue, data);
- free(data->cparam);
- free(data);
- }
-
- } while(ret_val < 0);
-
-failed:
- hci_close_dev(dd);
-
- return;
+ hci_req_queue_process(dev_id);
}
static inline int get_bdaddr(int dev, bdaddr_t *sba, uint16_t handle, bdaddr_t *dba)