summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hcid/dbus-todo.txt25
-rw-r--r--hcid/dbus.c83
-rw-r--r--hcid/hcid.h20
-rw-r--r--hcid/security.c146
4 files changed, 159 insertions, 115 deletions
diff --git a/hcid/dbus-todo.txt b/hcid/dbus-todo.txt
index b906a55d..3fecc3eb 100644
--- a/hcid/dbus-todo.txt
+++ b/hcid/dbus-todo.txt
@@ -7,25 +7,6 @@ Date: 2006/04/11
Description: Review these errors. The usage of "Does not exists"
and "Not available" are confusing.
-* pending HCI requests
-Date: 2006/04/11
-Description: The D-Bus authentication method creates automatically
-an ACL connection when required and disconnects when the procedure
-finishes. When the HCI connection complete arrives, remote name/
-version/features are queued. Considering that the authentication
-is not queued, when this procedure finishes and the disconnect is
-requested, the remaining elements in the queue can't be executed.
-
-* active connections verification
-Date: 2006/04/11
-Description: get_bdaddr function is called frequently in the
-security.c file. In a real usage scenario, the disconnect
-command can be sent by another process or BlueZ D-Bus method.
-On this case if there is pending request confirmation(eg: remote
-version complete or remote features complete), when the
-confirmation arrives the bdaddr can't be retrieved because
-there isn't active connection anymore. Suggestion: keep a active
-connection list instead of call the get_bdaddr frequently. Keep
-in mind that D-Bus data already has a list to store active
-connections.
-
+* code standard for sending msg function
+Date: 2006/04/13
+Description: use send_reply_and_unref when possible.
diff --git a/hcid/dbus.c b/hcid/dbus.c
index 3354da5f..cd864215 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -578,8 +578,7 @@ void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status)
{
struct hci_dbus_data *pdata;
- DBusMessage *msg_reply = NULL;
- DBusMessage *msg_signal = NULL;
+ DBusMessage *message = NULL;
char *local_addr, *peer_addr;
const char *name;
bdaddr_t tmp;
@@ -615,49 +614,38 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const u
*/
name = status ? "BondingFailed" : "BondingCreated";
/* authentication signal */
- msg_signal = dbus_message_new_signal(path, ADAPTER_INTERFACE, name);
-
- if (msg_signal == NULL) {
- error("Can't allocate D-Bus message");
- goto failed;
- }
-
- dbus_message_append_args(msg_signal,
- DBUS_TYPE_STRING, &peer_addr,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send(connection, msg_signal, NULL) == FALSE) {
- error("Can't send D-Bus bonding created signal");
- goto failed;
- }
+ message = dev_signal_factory(pdata->dev_id, name,
+ DBUS_TYPE_STRING, &peer_addr,
+ DBUS_TYPE_INVALID);
- dbus_connection_flush(connection);
+ send_reply_and_unref(connection, message);
if (!pdata->bonding)
goto failed; /* skip: no bonding req pending */
- msg_reply = dbus_msg_new_authentication_return(pdata->bonding->rq, status);
- if (dbus_connection_send(connection, msg_reply, NULL) == FALSE) {
- error("Can't send D-Bus reply for create bonding request");
- goto failed;
- }
-
- /* FIXME: disconnect if required */
if (pdata->bonding->disconnect) {
struct slist *l;
l = slist_find(pdata->active_conn, peer, active_conn_find_by_bdaddr);
if (l) {
struct active_conn_info *con = l->data;
- int dd = hci_open_dev(pdata->dev_id);
- /* Send the HCI disconnect command */
- if (hci_disconnect(dd, con->handle, HCI_OE_USER_ENDED_CONNECTION, 100) < 0) {
- error("Disconnect failed");
- }
- hci_close_dev(dd);
+ 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, peer, OGF_LINK_CTL,
+ OCF_DISCONNECT, EVT_DISCONN_COMPLETE,
+ &cp, DISCONNECT_CP_SIZE);
+ hci_req_queue_append(data);
}
}
+ message = dbus_msg_new_authentication_return(pdata->bonding->rq, status);
+ send_reply_and_unref(connection, message);
+
bonding_request_free(pdata->bonding);
pdata->bonding = NULL;
@@ -665,12 +653,6 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const u
pdata->requestor_name = NULL;
failed:
- if (msg_signal)
- dbus_message_unref(msg_signal);
-
- if (msg_reply)
- dbus_message_unref(msg_reply);
-
bt_free(local_addr);
bt_free(peer_addr);
}
@@ -1234,13 +1216,32 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle
goto failed;
dev = l->data;
- /* add in the active connetions list */
+
baswap(&tmp, &dev->bdaddr); peer_addr = batostr(&tmp);
- /* Sent the remote device disconnected signal */
- message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceDisconnected");
+ /* clean pending HCI cmds */
+ hci_req_queue_remove(pdata->dev_id, &dev->bdaddr);
- dbus_message_append_args(message,
+ /* Check if there is a pending Bonding */
+ if (pdata->bonding) {
+ message = dev_signal_factory(pdata->dev_id, "BondingFailed",
+ DBUS_TYPE_STRING, &peer_addr,
+ DBUS_TYPE_INVALID);
+
+ send_reply_and_unref(connection, message);
+
+ message = dbus_msg_new_authentication_return(pdata->bonding->rq, status);
+ send_reply_and_unref(connection, message);
+
+ bonding_request_free(pdata->bonding);
+ pdata->bonding = NULL;
+
+ free(pdata->requestor_name);
+ pdata->requestor_name = NULL;
+ }
+
+ /* Sent the remote device disconnected signal */
+ message = dev_signal_factory(pdata->dev_id, "RemoteDeviceDisconnected",
DBUS_TYPE_STRING, &peer_addr,
DBUS_TYPE_INVALID);
diff --git a/hcid/hcid.h b/hcid/hcid.h
index 2f5d74c1..066f9358 100644
--- a/hcid/hcid.h
+++ b/hcid/hcid.h
@@ -84,6 +84,26 @@ struct hcid_opts {
};
extern struct hcid_opts hcid;
+typedef enum {
+ REQ_PENDING,
+ REQ_SENT
+} req_status_t;
+
+struct hci_req_data {
+ int dev_id;
+ int event;
+ req_status_t status;
+ bdaddr_t dba;
+ uint16_t ogf;
+ uint16_t ocf;
+ void *cparam;
+ int clen;
+};
+
+struct hci_req_data *hci_req_data_new(int dev_id, const bdaddr_t *dba, uint16_t ogf, uint16_t ocf, int event, const void *cparam, int clen);
+void hci_req_queue_append(struct hci_req_data *data);
+void hci_req_queue_remove(int dev_id, bdaddr_t *dba);
+
#define HCID_SEC_NONE 0
#define HCID_SEC_AUTO 1
#define HCID_SEC_USER 2
diff --git a/hcid/security.c b/hcid/security.c
index 72fcc9e6..6f0aa10f 100644
--- a/hcid/security.c
+++ b/hcid/security.c
@@ -62,17 +62,9 @@ static struct g_io_info io_data[HCI_MAX_DEV];
static int pairing = HCID_PAIRING_MULTI;
-struct hci_req_data {
- int dev;
- uint16_t ogf;
- uint16_t ocf;
- void *cparam;
- int clen;
-};
-
static struct slist *hci_req_queue = NULL;
-static struct hci_req_data *hci_req_data_new(int dev, uint16_t ogf, uint16_t ocf, const void *cparam, int clen)
+struct hci_req_data *hci_req_data_new(int dev_id, const bdaddr_t *dba, uint16_t ogf, uint16_t ocf, int event, const void *cparam, int clen)
{
struct hci_req_data *data;
@@ -87,48 +79,103 @@ static struct hci_req_data *hci_req_data_new(int dev, uint16_t ogf, uint16_t ocf
free(data);
return NULL;
}
-
+
memcpy(data->cparam, cparam, clen);
- data->dev = dev;
+ bacpy(&data->dba, dba);
+
+ data->dev_id = dev_id;
+ data->status = REQ_PENDING;
data->ogf = ogf;
data->ocf = ocf;
+ data->event = event;
data->clen = clen;
return data;
}
-static int hci_req_find_by_dev(const void *data, const void *user_data)
+void hci_req_queue_append(struct hci_req_data *data)
+{
+ hci_req_queue = slist_append(hci_req_queue, data);
+}
+
+void hci_req_queue_remove(int dev_id, bdaddr_t *dba)
+{
+ struct slist *cur, *next;
+ struct hci_req_data *req;
+
+ for (cur = hci_req_queue; cur != NULL; cur = next) {
+ req = cur->data;
+ next = cur->next;
+ if ((req->dev_id != dev_id) || (bacmp(&req->dba, dba)))
+ continue;
+
+ hci_req_queue = slist_remove(hci_req_queue, req);
+ free(req->cparam);
+ free(req);
+ }
+}
+
+static int hci_req_find_by_devid(const void *data, const void *user_data)
{
const struct hci_req_data *req = data;
- const int *dev = user_data;
+ const int *dev_id = user_data;
- return (*dev - req->dev);
+ return (*dev_id - req->dev_id);
}
-static int check_pending_hci_req(int dev)
+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 -1;
+ return;
- l = slist_find(hci_req_queue, &dev, hci_req_find_by_dev);
+ /* find the first element(pending)*/
+ l = slist_find(hci_req_queue, &dev_id, hci_req_find_by_devid);
if (!l)
- return -1;
+ return;
data = l->data;
- hci_send_cmd(dev, data->ogf, data->ocf, data->clen, data->cparam);
+ /* skip if there is pending confirmation */
+ if (data->status == REQ_SENT) {
+ if (data->event != event)
+ return;
+
+ /* remove the confirmed cmd */
+ hci_req_queue = slist_remove(hci_req_queue, data);
+ free(data->cparam);
+ 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);
+ }
- hci_req_queue = slist_remove(hci_req_queue, data);
+ } while(ret_val < 0);
- free(data->cparam);
- free(data);
+failed:
+ hci_close_dev(dd);
- return 0;
+ return;
}
static inline int get_bdaddr(int dev, bdaddr_t *sba, uint16_t handle, bdaddr_t *dba)
@@ -412,9 +459,6 @@ static inline void remote_name_information(int dev, bdaddr_t *sba, void *ptr)
}
hcid_dbus_remote_name(sba, &dba, evt->status, name);
-
- /* pending remote version or remote features */
- check_pending_hci_req(dev);
}
static inline void remote_version_information(int dev, bdaddr_t *sba, void *ptr)
@@ -430,9 +474,6 @@ static inline void remote_version_information(int dev, bdaddr_t *sba, void *ptr)
write_version_info(sba, &dba, btohs(evt->manufacturer),
evt->lmp_ver, btohs(evt->lmp_subver));
-
- /* pending remote features */
- check_pending_hci_req(dev);
}
static inline void inquiry_complete(int dev, bdaddr_t *sba, void *ptr)
@@ -531,23 +572,13 @@ static inline void remote_features_information(int dev, bdaddr_t *sba, void *ptr
write_features_info(sba, &dba, evt->features);
}
-static inline void name_resolve(int dev, bdaddr_t *bdaddr)
-{
- remote_name_req_cp cp;
-
- memset(&cp, 0, sizeof(cp));
- bacpy(&cp.bdaddr, bdaddr);
- cp.pscan_rep_mode = 0x02;
-
- hci_send_cmd(dev, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ,
- REMOTE_NAME_REQ_CP_SIZE, &cp);
-}
-
-static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr)
+static inline void conn_complete(int dev, int dev_id, bdaddr_t *sba, void *ptr)
{
evt_conn_complete *evt = ptr;
char filename[PATH_MAX];
+ remote_name_req_cp cp_name;
bdaddr_t tmp;
+ struct hci_req_data *data;
char *str, *local_addr, *peer_addr;
hcid_dbus_conn_complete(sba, evt->status, evt->handle, &evt->bdaddr);
@@ -557,7 +588,16 @@ static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr)
update_lastused(sba, &evt->bdaddr);
- name_resolve(dev, &evt->bdaddr);
+ /* Request remote name */
+ memset(&cp_name, 0, sizeof(cp_name));
+ bacpy(&cp_name.bdaddr, &evt->bdaddr);
+ cp_name.pscan_rep_mode = 0x02;
+
+ data = hci_req_data_new(dev_id, &evt->bdaddr, OGF_LINK_CTL,
+ OCF_REMOTE_NAME_REQ, EVT_REMOTE_NAME_REQ_COMPLETE,
+ &cp_name, REMOTE_NAME_REQ_CP_SIZE);
+
+ hci_req_queue_append(data);
/* check if the remote version needs be requested */
baswap(&tmp, sba); local_addr = batostr(&tmp);
@@ -568,15 +608,15 @@ static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr)
str = textfile_get(filename, peer_addr);
if (!str) {
- struct hci_req_data *data;
read_remote_version_cp cp;
cp.handle = evt->handle;
- data = hci_req_data_new(dev, OGF_LINK_CTL, OCF_READ_REMOTE_VERSION,
- &cp, READ_REMOTE_VERSION_CP_SIZE);
+ data = hci_req_data_new(dev_id, &evt->bdaddr, OGF_LINK_CTL,
+ OCF_READ_REMOTE_VERSION, EVT_READ_REMOTE_VERSION_COMPLETE,
+ &cp, READ_REMOTE_VERSION_CP_SIZE);
- hci_req_queue = slist_append(hci_req_queue, data);
+ hci_req_queue_append(data);
} else {
/* skip: remote version found */
free(str);
@@ -588,15 +628,15 @@ static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr)
str = textfile_get(filename, peer_addr);
if (!str) {
- struct hci_req_data *data;
read_remote_features_cp cp;
cp.handle = evt->handle;
- data = hci_req_data_new(dev, OGF_LINK_CTL, OCF_READ_REMOTE_FEATURES,
- &cp, READ_REMOTE_FEATURES_CP_SIZE);
+ data = hci_req_data_new(dev_id, &evt->bdaddr, OGF_LINK_CTL,
+ OCF_READ_REMOTE_FEATURES, EVT_READ_REMOTE_FEATURES_COMPLETE,
+ &cp, READ_REMOTE_FEATURES_CP_SIZE);
- hci_req_queue = slist_append(hci_req_queue, data);
+ hci_req_queue_append(data);
} else {
/* skip: remote features found */
free(str);
@@ -702,7 +742,7 @@ static gboolean io_security_event(GIOChannel *chan, GIOCondition cond, gpointer
break;
case EVT_CONN_COMPLETE:
- conn_complete(dev, &di->bdaddr, ptr);
+ conn_complete(dev, di->dev_id, &di->bdaddr, ptr);
break;
case EVT_DISCONN_COMPLETE:
@@ -713,6 +753,8 @@ static gboolean io_security_event(GIOChannel *chan, GIOCondition cond, gpointer
auth_complete(dev, &di->bdaddr, ptr);
break;
}
+ /* check for pending cmd request */
+ check_pending_hci_req(di->dev_id, eh->evt);
if (hci_test_bit(HCI_SECMGR, &di->flags))
return TRUE;