From 07472b3039243a4b273141bdb9a0a58d6150fbe8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 1 Oct 2005 10:04:51 +0000 Subject: [PATCH] hcidump: Add SCO audio extraction support --- tools/hcidump.1 | 9 ++++++--- tools/hcidump.c | 28 ++++++++++++++++++++-------- tools/parser/hci.c | 3 +++ tools/parser/l2cap.c | 1 + tools/parser/obex.c | 1 + tools/parser/parser.c | 4 +++- tools/parser/parser.h | 5 ++++- tools/parser/sdp.c | 1 + 8 files changed, 39 insertions(+), 13 deletions(-) diff --git a/tools/hcidump.1 b/tools/hcidump.1 index 457b51c4d..e7ce4c28f 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=" "" Sets the PSM value for the CAPI Message Transport Protocol. .TP -.BR -H ", " "\-\^\-hcrp" +.BR -H ", " "\-\^\-hcrp=" "" Sets the PSM value for the Hardcopy Control Channel. .TP -.BR -O ", " "\-\^\-obex" +.BR -O ", " "\-\^\-obex=" "" Sets the RFCOMM channel value for the Object Exchange protocol. .TP +.BR -A ", " "\-\^\-audio=" "" +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 9f7f866e3..bd2e0730e 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 ca44dffb3..a65193057 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 168ad6f25..38adc593a 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 9e5a509d9..2e5ee4333 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 fbbd045e7..34ae4e584 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 d515ddd43..ffcc454df 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 7a360a85e..e5a750ab9 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; } -- 2.47.3