Diff between 185403dadacfae3e89b1a97c0bfcab842eba24e2 and 07472b3039243a4b273141bdb9a0a58d6150fbe8

Changed Files

File Additions Deletions Status
tools/hcidump.1 +6 -3 modified
tools/hcidump.c +20 -8 modified
tools/parser/hci.c +3 -0 modified
tools/parser/l2cap.c +1 -0 modified
tools/parser/obex.c +1 -0 modified
tools/parser/parser.c +3 -1 modified
tools/parser/parser.h +4 -1 modified
tools/parser/sdp.c +1 -0 modified

Full Patch

diff --git a/tools/hcidump.1 b/tools/hcidump.1
index 457b51c..e7ce4c2 100644
--- a/tools/hcidump.1
+++ b/tools/hcidump.1
@@ -79,15 +79,18 @@ For every packet, not only is the packet type displayed, but also all data in he
 .BR -R ", " "\-\^\-raw"
 For every packet, only the raw data is displayed.
 .TP
-.BR -C ", " "\-\^\-cmtp"
+.BR -C ", " "\-\^\-cmtp=" "<psm>"
 Sets the PSM value for the CAPI Message Transport Protocol.
 .TP
-.BR -H ", " "\-\^\-hcrp"
+.BR -H ", " "\-\^\-hcrp=" "<psm>"
 Sets the PSM value for the Hardcopy Control Channel.
 .TP
-.BR -O ", " "\-\^\-obex"
+.BR -O ", " "\-\^\-obex=" "<channel>"
 Sets the RFCOMM channel value for the Object Exchange protocol.
 .TP
+.BR -A ", " "\-\^\-audio=" "<file>"
+Extract SCO audio data.
+.TP
 .BR -B ", " "\-\^\-btsnoop"
 Use the BTSnoop file format.
 .TP
diff --git a/tools/hcidump.c b/tools/hcidump.c
index 9f7f866..bd2e073 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
@@ -76,7 +76,8 @@ enum {
 	READ,
 	WRITE,
 	RECEIVE,
-	SEND
+	SEND,
+	AUDIO
 };
 
 /* Default options */
@@ -88,7 +89,8 @@ static int  mode = PARSE;
 static int  permcheck = 1;
 static long flags;
 static long filter;
-static char *dump_file;
+static char *dump_file = NULL;
+static char *audio_file = NULL;
 static in_addr_t dump_addr = INADDR_LOOPBACK;
 static in_port_t dump_port = DEFAULT_PORT;
 
@@ -218,6 +220,7 @@ static void process_frames(int dev, int sock, int fd, unsigned long flags)
 		frm.data_len = len;
 		frm.dev_id = dev;
 		frm.in = 0;
+		frm.audio_fd = parser.audio_fd;
 
 		cmsg = CMSG_FIRSTHDR(&msg);
 		while (cmsg) {
@@ -357,7 +360,7 @@ static int open_file(char *file, int mode, unsigned long flags)
 	struct btsnoop_hdr hdr;
 	int fd, len, open_flags;
 
-	if (mode == WRITE) {
+	if (mode == WRITE || mode == AUDIO) {
 		if (flags & DUMP_BTSNOOP)
 			open_flags = O_WRONLY | O_CREAT;
 		else
@@ -643,6 +646,7 @@ static void usage(void)
 	"  -C, --cmtp=psm             PSM for CMTP\n"
 	"  -H, --hcrp=psm             PSM for HCRP\n"
 	"  -O, --obex=channel         Channel for OBEX\n"
+	"  -A, --audio=file           Extract SCO audio data\n"
 	"  -B, --btsnoop              Use BTSnoop file format\n"
 	"  -V, --verbose              Verbose decoding\n"
 	"  -h, --help                 Give this help list\n"
@@ -667,6 +671,7 @@ static struct option main_options[] = {
 	{ "cmtp",		1, 0, 'C' },
 	{ "hcrp",		1, 0, 'H' },
 	{ "obex",		1, 0, 'O' },
+	{ "audio",		1, 0, 'A' },
 	{ "btsnoop",		0, 0, 'B' },
 	{ "verbose",		0, 0, 'V' },
 	{ "help",		0, 0, 'h' },
@@ -677,11 +682,11 @@ int main(int argc, char *argv[])
 {
 	struct hostent *host;
 	struct in_addr addr;
-	int opt;
+	int opt, fd = -1;
 
 	printf("HCI sniffer - Bluetooth packet analyzer ver %s\n", VERSION);
 
-	while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:taxXRC:H:O:BVZh", main_options, NULL)) != -1) {
+	while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:taxXRC:H:O:A:BVZh", main_options, NULL)) != -1) {
 		switch(opt) {
 		case 'i':
 			if (strcasecmp(optarg, "none") && strcasecmp(optarg, "system"))
@@ -770,6 +775,10 @@ int main(int argc, char *argv[])
 			set_proto(0, 0, atoi(optarg), SDP_UUID_OBEX);
 			break;
 
+		case 'A':
+			audio_file = strdup(optarg);
+			break;
+
 		case 'B':
 			flags |= DUMP_BTSNOOP;
 			break;
@@ -800,14 +809,17 @@ int main(int argc, char *argv[])
 	if (!filter)
 		filter = ~0L;
 
+	if (audio_file)
+		fd = open_file(audio_file, AUDIO, flags);
+
 	switch (mode) {
 	case PARSE:
-		init_parser(flags, filter, defpsm, defcompid);
+		init_parser(flags, filter, defpsm, defcompid, fd);
 		process_frames(device, open_socket(device, flags), -1, flags);
 		break;
 
 	case READ:
-		init_parser(flags, filter, defpsm, defcompid);
+		init_parser(flags, filter, defpsm, defcompid, fd);
 		read_dump(open_file(dump_file, mode, flags));
 		break;
 
@@ -817,7 +829,7 @@ int main(int argc, char *argv[])
 		break;
 
 	case RECEIVE:
-		init_parser(flags, filter, defpsm, defcompid);
+		init_parser(flags, filter, defpsm, defcompid, fd);
 		read_dump(wait_connection(dump_addr, dump_port));
 		break;
 
diff --git a/tools/parser/hci.c b/tools/parser/hci.c
index ca44dff..a651930 100644
--- a/tools/parser/hci.c
+++ b/tools/parser/hci.c
@@ -2450,6 +2450,9 @@ static inline void sco_dump(int level, struct frame *frm)
 	hci_sco_hdr *hdr = (void *) frm->ptr;
 	uint16_t handle = btohs(hdr->handle);
 
+	if (frm->audio_fd > 2)
+		write(frm->audio_fd, frm->ptr + HCI_SCO_HDR_SIZE, hdr->dlen);
+
 	if (!p_filter(FILT_SCO)) {
 		p_indent(level, frm);
 		printf("SCO data: handle %d dlen %d\n",
diff --git a/tools/parser/l2cap.c b/tools/parser/l2cap.c
index 168ad6f..38adc59 100644
--- a/tools/parser/l2cap.c
+++ b/tools/parser/l2cap.c
@@ -870,6 +870,7 @@ void l2cap_dump(int level, struct frame *frm)
 		fr->num      = frm->num;
 		fr->dlci     = frm->dlci;
 		fr->channel  = frm->channel;
+		fr->audio_fd = frm->audio_fd;
 	} else {
 		if (!(fr = get_frame(frm->handle))) {
 			fprintf(stderr, "Not enough connection handles\n");
diff --git a/tools/parser/obex.c b/tools/parser/obex.c
index 9e5a509..2e5ee43 100644
--- a/tools/parser/obex.c
+++ b/tools/parser/obex.c
@@ -112,6 +112,7 @@ static struct frame *add_frame(struct frame *frm)
 	fr->num      = frm->num;
 	fr->dlci     = frm->dlci;
 	fr->channel  = frm->channel;
+	fr->audio_fd = frm->audio_fd;
 
 	return fr;
 }
diff --git a/tools/parser/parser.c b/tools/parser/parser.c
index fbbd045..34ae4e5 100644
--- a/tools/parser/parser.c
+++ b/tools/parser/parser.c
@@ -40,7 +40,8 @@
 struct parser_t parser;
 
 void init_parser(unsigned long flags, unsigned long filter,
-		unsigned short defpsm, unsigned short defcompid)
+		unsigned short defpsm, unsigned short defcompid,
+		int audio_fd)
 {
 	if ((flags & DUMP_RAW) && !(flags & DUMP_TYPE_MASK))
 		flags |= DUMP_HEX;
@@ -50,6 +51,7 @@ void init_parser(unsigned long flags, unsigned long filter,
 	parser.defpsm    = defpsm;
 	parser.defcompid = defcompid;
 	parser.state     = 0;
+	parser.audio_fd  = audio_fd;
 }
 
 #define PROTO_TABLE_SIZE 20
diff --git a/tools/parser/parser.h b/tools/parser/parser.h
index d515ddd..ffcc454 100644
--- a/tools/parser/parser.h
+++ b/tools/parser/parser.h
@@ -47,6 +47,7 @@ struct frame {
 	uint8_t		channel;
 	unsigned long	flags;
 	struct timeval	ts;
+	int		audio_fd;
 };
 
 /* Parser flags */
@@ -94,12 +95,14 @@ struct parser_t {
 	unsigned short defpsm;
 	unsigned short defcompid;
 	int state;
+	int audio_fd;
 };
 
 extern struct parser_t parser;
 
 void init_parser(unsigned long flags, unsigned long filter, 
-		unsigned short defpsm, unsigned short defcompid);
+		unsigned short defpsm, unsigned short defcompid,
+		int audio_fd);
 
 static inline int p_filter(unsigned long f)
 {
diff --git a/tools/parser/sdp.c b/tools/parser/sdp.c
index 7a360a8..e5a750a 100644
--- a/tools/parser/sdp.c
+++ b/tools/parser/sdp.c
@@ -611,6 +611,7 @@ static int add_frame(struct frame *frm, int count)
 	fr->cid      = frm->cid;
 	fr->num      = frm->num;
 	fr->channel  = frm->channel;
+	fr->audio_fd = frm->audio_fd;
 
 	return pos;
 }