summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2011-01-21 13:55:44 +0200
committerJohan Hedberg <johan.hedberg@nokia.com>2011-01-21 13:55:44 +0200
commit1e862b561c65fb0d6096cd93d2c9cfe11f0356bb (patch)
treef1aa8c938a017495e435c5521b78cb3108e3a764
parentcc0e50e3ab1a612ffb72b9021229f660d54f9388 (diff)
downloadbluez-1e862b561c65fb0d6096cd93d2c9cfe11f0356bb.tar.gz
mgmt: add support for get_connections command
-rw-r--r--doc/mgmt-api.txt12
-rw-r--r--lib/mgmt.h10
-rw-r--r--plugins/mgmtops.c66
3 files changed, 86 insertions, 2 deletions
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 00b2b37a9..613b7fca3 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -191,6 +191,18 @@ Disconnect Command
Return Paramters: Controller_Index (2 Octets)
Address (6 Octets)
+Get Connections Command
+=======================
+
+ Command Code: 0x0010
+ Command Parameters: Controller_Index (2 Octets)
+ Return Paramters: Controller_Index (2 Octets)
+ Connection_Count (2 Octets)
+ Address1 (6 Octets)
+ Address2 (6 Octets)
+ ...
+
+
Read Tracing Buffer Size Command
================================
diff --git a/lib/mgmt.h b/lib/mgmt.h
index 11811cd64..e9079fff7 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -139,6 +139,16 @@ struct mgmt_rp_disconnect {
bdaddr_t bdaddr;
} __packed;
+#define MGMT_OP_GET_CONNECTIONS 0x0010
+struct mgmt_cp_get_connections {
+ uint16_t index;
+} __packed;
+struct mgmt_rp_get_connections {
+ uint16_t index;
+ uint16_t conn_count;
+ bdaddr_t conn[0];
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
uint16_t opcode;
diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index d80f29d52..ed82f8b53 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -66,6 +66,7 @@ static struct controller_info {
gboolean discoverable;
gboolean pairable;
uint8_t sec_mode;
+ GSList *connections;
} *controllers = NULL;
static int mgmt_sock = -1;
@@ -128,6 +129,23 @@ static void read_info(int sk, uint16_t index)
strerror(errno), errno);
}
+static void get_connections(int sk, uint16_t index)
+{
+ char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_get_connections)];
+ struct mgmt_hdr *hdr = (void *) buf;
+ struct mgmt_cp_get_connections *cp = (void *) &buf[sizeof(*hdr)];
+
+ memset(buf, 0, sizeof(buf));
+ hdr->opcode = htobs(MGMT_OP_GET_CONNECTIONS);
+ hdr->len = htobs(sizeof(*cp));
+
+ cp->index = htobs(index);
+
+ if (write(sk, buf, sizeof(buf)) < 0)
+ error("Unable to send get_connections command: %s (%d)",
+ strerror(errno), errno);
+}
+
static void mgmt_index_added(int sk, void *buf, size_t len)
{
struct mgmt_ev_index_added *ev = buf;
@@ -601,7 +619,7 @@ static void read_index_list_complete(int sk, void *buf, size_t len)
index = btohs(bt_get_unaligned(&rp->index[i]));
add_controller(index);
- read_info(sk, index);
+ get_connections(sk, index);
clear_uuids(index);
}
}
@@ -824,6 +842,41 @@ static void disconnect_complete(int sk, void *buf, size_t len)
btd_event_disconn_complete(&info->bdaddr, &rp->bdaddr);
}
+static void get_connections_complete(int sk, void *buf, size_t len)
+{
+ struct mgmt_rp_get_connections *rp = buf;
+ struct controller_info *info;
+ uint16_t index;
+ int i;
+
+ if (len < sizeof(*rp)) {
+ error("Too small get_connections complete event");
+ return;
+ }
+
+ if (len < (sizeof(*rp) + (rp->conn_count * sizeof(bdaddr_t)))) {
+ error("Too small get_connections complete event");
+ return;
+ }
+
+ index = btohs(bt_get_unaligned(&rp->index));
+
+ if (index > max_index) {
+ error("Unexpected index %u in get_connections complete",
+ index);
+ return;
+ }
+
+ info = &controllers[index];
+
+ for (i = 0; i < rp->conn_count; i++) {
+ bdaddr_t *bdaddr = g_memdup(&rp->conn[i], sizeof(bdaddr_t));
+ info->connections = g_slist_append(info->connections, bdaddr);
+ }
+
+ read_info(sk, index);
+}
+
static void mgmt_cmd_complete(int sk, void *buf, size_t len)
{
struct mgmt_ev_cmd_complete *ev = buf;
@@ -882,6 +935,9 @@ static void mgmt_cmd_complete(int sk, void *buf, size_t len)
DBG("disconnect complete");
disconnect_complete(sk, ev->data, len - sizeof(*ev));
break;
+ case MGMT_OP_GET_CONNECTIONS:
+ get_connections_complete(sk, ev->data, len - sizeof(*ev));
+ break;
default:
error("Unknown command complete for opcode %u", opcode);
break;
@@ -1204,8 +1260,14 @@ static int mgmt_unblock_device(int index, bdaddr_t *bdaddr)
static int mgmt_get_conn_list(int index, GSList **conns)
{
+ struct controller_info *info = &controllers[index];
+
DBG("index %d", index);
- return -ENOSYS;
+
+ *conns = info->connections;
+ info->connections = NULL;
+
+ return 0;
}
static int mgmt_read_local_version(int index, struct hci_version *ver)