Diff between 7941078420c7b6114e17689645a0ccc25a5eee41 and 68b5421b744554b61be3a251666bffc5ab7e6b46

Changed Files

File Additions Deletions Status
Makefile.tools +1 -0 modified
mgmt/main.c +107 -3 modified

Full Patch

diff --git a/Makefile.tools b/Makefile.tools
index 24db948..ff93bc9 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -51,6 +51,7 @@ tools_hcieventmask_LDADD = lib/libbluetooth-private.la
 
 noinst_PROGRAMS += mgmt/btmgmt
 mgmt_btmgmt_SOURCES = mgmt/main.c
+mgmt_btmgmt_LDADD = lib/libbluetooth-private.la
 
 if READLINE
 bin_PROGRAMS += attrib/gatttool
diff --git a/mgmt/main.c b/mgmt/main.c
index c8ebcc7..7abd509 100644
--- a/mgmt/main.c
+++ b/mgmt/main.c
@@ -37,6 +37,54 @@
 #include <bluetooth/hci.h>
 #include <bluetooth/mgmt.h>
 
+typedef void (*cmd_cb)(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
+				void *rsp, uint16_t len, void *user_data);
+
+static struct {
+	uint16_t op;
+	uint16_t id;
+	cmd_cb cb;
+	void *user_data;
+} *pending_cmd = NULL;
+
+static int mgmt_send_cmd(int mgmt_sk, uint16_t op, uint16_t id, void *data,
+				size_t len, cmd_cb func, void *user_data)
+{
+	char buf[1024];
+	struct mgmt_hdr *hdr = (void *) buf;
+
+	if (pending_cmd != NULL)
+		return -EBUSY;
+
+	if (len + MGMT_HDR_SIZE > sizeof(buf))
+		return -EINVAL;
+
+	pending_cmd = malloc(sizeof(*pending_cmd));
+	if (pending_cmd == NULL)
+		return -errno;
+
+	pending_cmd->op = op;
+	pending_cmd->id = id;
+	pending_cmd->cb = func;
+	pending_cmd->user_data = user_data;
+
+	memset(buf, 0, sizeof(buf));
+	hdr->opcode = htobs(MGMT_OP_READ_INFO);
+	hdr->index = htobs(id);
+	hdr->len = htobs(len);
+	memcpy(buf + MGMT_HDR_SIZE, data, len);
+
+	if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
+		fprintf(stderr, "Unable to send command: %s\n",
+							strerror(errno));
+		free(pending_cmd);
+		pending_cmd = NULL;
+		return -1;
+	}
+
+	return 0;
+}
+
 static int mgmt_open(void)
 {
 	struct sockaddr_hci addr;
@@ -65,7 +113,7 @@ static int mgmt_open(void)
 static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
 				struct mgmt_ev_cmd_complete *ev, uint16_t len)
 {
-	uint16_t opcode;
+	uint16_t op;
 
 	if (len < sizeof(*ev)) {
 		fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
@@ -73,11 +121,18 @@ static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
 		return -EINVAL;
 	}
 
-	opcode = bt_get_le16(&ev->opcode);
+	op = bt_get_le16(&ev->opcode);
 
 	len -= sizeof(*ev);
 
-	printf("cmd complete, opcode 0x%04x len %u\n", opcode, len);
+	printf("cmd complete, opcode 0x%04x len %u\n", op, len);
+
+	if (pending_cmd != NULL && op == pending_cmd->op) {
+		pending_cmd->cb(mgmt_sk, op, index, 0, ev->data, len,
+						pending_cmd->user_data);
+		free(pending_cmd);
+		pending_cmd = NULL;
+	}
 
 	return 0;
 }
@@ -97,6 +152,14 @@ static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
 
 	printf("cmd status, opcode 0x%04x status 0x%02x\n", opcode, ev->status);
 
+	if (ev->status != 0 && pending_cmd != NULL &&
+						opcode == pending_cmd->op) {
+		pending_cmd->cb(mgmt_sk, opcode, index, ev->status,
+					NULL, 0, pending_cmd->user_data);
+		free(pending_cmd);
+		pending_cmd = NULL;
+	}
+
 	return 0;
 }
 
@@ -251,12 +314,53 @@ static void cmd_monitor(int mgmt_sk, int argc, char **argv)
 	printf("Monitoring mgmt events...\n");
 }
 
+static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
+				void *rsp, uint16_t len, void *user_data)
+{
+	struct mgmt_rp_read_info *rp = rsp;
+	char addr[18];
+
+	if (status != 0) {
+		printf("Reading controller %u info failed with status %u\n",
+								id, status);
+		exit(EXIT_FAILURE);
+	}
+
+	ba2str(&rp->bdaddr, addr);
+	printf("hci%u:\ttype %u addr %s\n", id, rp->type, addr);
+	printf("\tclass 0x%02x%02x%02x\n",
+		rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+	printf("\tmanufacturer %d HCI ver %d:%d\n",
+					bt_get_le16(&rp->manufacturer),
+					rp->hci_ver, bt_get_le16(&rp->hci_rev));
+	printf("\tpowered %u discoverable %u pairable %u sec_mode %u\n",
+				rp->powered, rp->discoverable,
+				rp->pairable, rp->sec_mode);
+	printf("\tname %s\n", (char *) rp->name);
+	exit(EXIT_SUCCESS);
+}
+
+static void cmd_info(int mgmt_sk, int argc, char **argv)
+{
+	if (argc < 2) {
+		printf("Controller id needed\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, atoi(argv[1]), NULL,
+						0, info_rsp, NULL) < 0) {
+		fprintf(stderr, "Unable to send cmd\n");
+		exit(EXIT_FAILURE);
+	}
+}
+
 static struct {
 	char *cmd;
 	void (*func)(int mgmt_sk, int argc, char **argv);
 	char *doc;
 } command[] = {
 	{ "monitor",	cmd_monitor,	"Monitor events"		},
+	{ "info",	cmd_info,	"Show controller info"		},
 	{ NULL, NULL, 0 }
 };