[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-bluetooth
Subject: [PATCH 4/4] tools/hcidump: Add support to read snoop via ADB
From: Andrzej Kaczmarek <andrzej.kaczmarek () tieto ! com>
Date: 2014-05-30 16:15:56
Message-ID: 1401466556-9040-4-git-send-email-andrzej.kaczmarek () tieto ! com
[Download RAW message or body]
Reading from ADB requires bluetoothd-snoop service to be running on
target device (i.e. HCI logging needs to be turned on in case of KitKat
devices).
Without optional argument, "-d" or "--read-adb" will connect to default
device and use default port (4330). Optional argument can be in form:
<serialno>:<port>
Any of <serialno> and <port> can be omitted and default value will be
used, i.e. --read-adb=ABCD will read from device with serial ABCD and
port 4330 while --read-adb=:1234 will read from default device and port
1234.
---
tools/hcidump.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 165 insertions(+), 2 deletions(-)
diff --git a/tools/hcidump.c b/tools/hcidump.c
index 37a9f00..3dff7d6 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
@@ -38,6 +38,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <arpa/inet.h>
#include "parser/parser.h"
#include "parser/sdp.h"
@@ -53,7 +54,8 @@ enum {
READ,
WRITE,
PPPDUMP,
- AUDIO
+ AUDIO,
+ ADB,
};
/* Default options */
@@ -522,6 +524,153 @@ static int open_file(char *file, int mode, unsigned long flags)
return fd;
}
+static int send_adb(int fd, const char *cmd)
+{
+ char buf[128];
+ unsigned int len;
+ struct iovec iov[2];
+
+ len = strlen(cmd);
+ sprintf(buf, "%04X", len);
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 4;
+ iov[1].iov_base = (void *) cmd;
+ iov[1].iov_len = len;
+
+ if (writev(fd, iov, 2) < 0)
+ return -1;
+
+ if (recv(fd, buf, sizeof(buf), 0) < 0)
+ return -1;
+
+ /* OKAY means we're fine */
+ if (!memcmp("OKAY", buf, 4))
+ return 0;
+
+ /*
+ * failure comes in format FAIL<4hex><msg> where <4hex> is length of
+ * <msg> written as hexadecimal string (4 chars)
+ */
+ if (sscanf(buf, "FAIL%04X", &len) > 0) {
+ buf[8 + len] = '\0';
+ fprintf(stderr, "ADB: %s\n", &buf[8]);
+ } else {
+ fprintf(stderr, "ADB: unknown failure");
+ }
+
+ return -1;
+}
+
+static int connect_adb(const char *serial, int port)
+{
+ struct sockaddr_in addr;
+ char cmd[128];
+ int fd;
+
+ fd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (fd < 0) {
+ perror("Failed to open TCP client socket");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ addr.sin_port = htons(5037); /* default ADB port */
+
+ if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("Failed to connect TCP client socket");
+ close(fd);
+ return -1;
+ }
+
+ /* first need to switch socket to adb daemon on device */
+ if (serial)
+ sprintf(cmd, "host:transport:%s", serial);
+ else
+ strcpy(cmd, "host:transport-any");
+ if (send_adb(fd, cmd) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ /* next need to switch socket to tcp socket */
+ sprintf(cmd, "tcp:%d", port ? port : 4330);
+ if (send_adb(fd, cmd) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static void parse_adb(const char *device, char **serial, int *port)
+{
+ const char *p;
+
+ *serial = NULL;
+ *port = 0;
+
+ if (!device)
+ return;
+
+ p = strrchr(device, ':');
+ if (!p) {
+ *serial = strdup(device);
+ return;
+ }
+
+ if (p - device)
+ *serial = strndup(device, p - device);
+ *port = atoi(&p[1]);
+}
+
+static int open_adb(const char *device)
+{
+ unsigned char buf[BTSNOOP_HDR_SIZE];
+ struct btsnoop_hdr *hdr = (struct btsnoop_hdr *) buf;
+ int fd, len;
+ char *serial;
+ int port;
+
+ parse_adb(device, &serial, &port);
+
+ fd = connect_adb(serial, port);
+ if (fd < 0)
+ return -1;
+
+ free(serial);
+
+ len = read(fd, buf, BTSNOOP_HDR_SIZE);
+ if (len != BTSNOOP_HDR_SIZE)
+ return -1;
+
+ if (memcmp(hdr->id, btsnoop_id, sizeof(btsnoop_id)))
+ return -1;
+
+ parser.flags |= DUMP_BTSNOOP;
+
+ btsnoop_version = be32toh(hdr->version);
+ btsnoop_type = be32toh(hdr->type);
+
+ printf("btsnoop version: %d datalink type: %d\n",
+ btsnoop_version, btsnoop_type);
+
+ if (btsnoop_version != 1) {
+ fprintf(stderr, "Unsupported BTSnoop version\n");
+ exit(1);
+ }
+
+ if (btsnoop_type != 1001 && btsnoop_type != 1002 &&
+ btsnoop_type != 2001) {
+ fprintf(stderr, "Unsupported BTSnoop datalink type\n");
+ exit(1);
+ }
+
+ return fd;
+}
+
static int open_socket(int dev, unsigned long flags)
{
struct sockaddr_hci addr;
@@ -624,6 +773,7 @@ static void usage(void)
" -m, --manufacturer=compid Default manufacturer\n"
" -w, --save-dump=file Save dump to a file\n"
" -r, --read-dump=file Read dump from a file\n"
+ " -d, --read-adb=dev Read dump via ADB\n"
" -t, --ts Display time stamps\n"
" -a, --ascii Dump data in ascii\n"
" -x, --hex Dump data in hex\n"
@@ -650,6 +800,7 @@ static struct option main_options[] = {
{ "manufacturer", 1, 0, 'm' },
{ "save-dump", 1, 0, 'w' },
{ "read-dump", 1, 0, 'r' },
+ { "read-adb", 2, 0, 'd' },
{ "timestamp", 0, 0, 't' },
{ "ascii", 0, 0, 'a' },
{ "hex", 0, 0, 'x' },
@@ -679,7 +830,7 @@ int main(int argc, char *argv[])
uint16_t obex_port;
while ((opt = getopt_long(argc, argv,
- "i:l:p:m:w:r:taxXRC:H:O:P:S:D:A:Yhv",
+ "i:l:p:m:w:r:d::taxXRC:H:O:P:S:D:A:Yhv",
main_options, NULL)) != -1) {
switch(opt) {
case 'i':
@@ -711,6 +862,11 @@ int main(int argc, char *argv[])
dump_file = strdup(optarg);
break;
+ case 'd':
+ mode = ADB;
+ dump_file = optarg ? strdup(optarg) : NULL;
+ break;
+
case 't':
flags |= DUMP_TSTAMP;
break;
@@ -817,6 +973,13 @@ int main(int argc, char *argv[])
process_frames(device, open_socket(device, flags),
open_file(dump_file, mode, flags), flags);
break;
+
+ case ADB:
+ flags |= DUMP_VERBOSE;
+ init_parser(flags, filter, defpsm, defcompid,
+ pppdump_fd, audio_fd);
+ read_dump(open_adb(dump_file));
+ break;
}
return 0;
--
1.9.3
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic