Adds an initial implementation for RFCOMM in Bluetooth monitor.
Implementation for Decoding MSC, RPN, RLS, PN, NSC frames
will be covered in the next patch-set.
v1: Added rfcomm.c file in Android.mk
v2: Adds the btmon log specific to rfcomm
Bharat Panda (2):
monitor/rfcomm: Add handlers for mcc frame type
monitor/rfcomm: Add mcc type handlers code
Gowtham Anandha Babu (4):
monitor/rfcomm: Add RFCOMM support to btmon
monitor/rfcomm: Add support for RFCOMM commands
monitor/rfcomm: Add support for UIH frame decoding
monitor/rfcomm: Add support for mcc frame decoding
Makefile.tools | 1 +
android/Android.mk | 1 +
monitor/l2cap.c | 4 +
monitor/l2cap.h | 1 +
monitor/rfcomm.c | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 340 insertions(+)
create mode 100644 monitor/rfcomm.c
--
1.9.1
Hi,
> -----Original Message-----
> From: [email protected] [mailto:linux-bluetooth-
> [email protected]] On Behalf Of Gowtham Anandha Babu
> Sent: Wednesday, November 05, 2014 5:55 PM
> To: 'Luiz Augusto von Dentz'
> Cc: [email protected]; 'Dmitry Kasatkin'; 'Bharat Panda';
> [email protected]
> Subject: RE: [PATCH v2 6/6] monitor/rfcomm: Add mcc type handlers code
>
> Hi,
>
> > -----Original Message-----
> > From: Luiz Augusto von Dentz [mailto:[email protected]]
> > Sent: Tuesday, November 04, 2014 5:46 PM
> > To: Gowtham Anandha Babu
> > Cc: [email protected]; Dmitry Kasatkin; Bharat Panda;
> > [email protected]
> > Subject: Re: [PATCH v2 6/6] monitor/rfcomm: Add mcc type handlers code
> >
> > Hi,
> >
> > On Mon, Nov 3, 2014 at 5:25 PM, Gowtham Anandha Babu
> > <[email protected]> wrote:
> > > From: Bharat Panda <[email protected]>
> > >
> > > Adds different mcc type handlers code to print in btmon.
> > > ---
> > > Below provided is the btmon rfcomm logs.
> > >> ACL Data RX: Handle 75 flags 0x02 dlen 8 [hci0] 22.280283
> > > Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
> > > RFCOMM(s): SABM
> > > Address : (0x83)
> > > CR Bit: 1
> > > DLCI : (0x20)
> > > Poll/FInal Bit : 1
> > > Length : 0
> > > FCS : (0xca)
> > > < ACL Data TX: Handle 75 flags 0x00 dlen 8 [hci0] 22.317803
> > > Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
> > > RFCOMM(s): UA
> > > Address : (0x83)
> > > CR Bit: 1
> > > DLCI : (0x20)
> > > Poll/FInal Bit : 1
> > > Length : 0
> > > FCS : (0x01)
> > > < ACL Data TX: Handle 75 flags 0x00 dlen 12 [hci0] 22.317822
> > > Channel: 65 len 8 [PSM 3 mode 0] {chan 1}
> > > RFCOMM(s): MSC CMD
> > > Address : (0x01)
> > > CR Bit: 0
> > > DLCI : (0x00)
> > > Poll/FInal Bit : 0
> > > Length : 4
> > > FCS : (0xaa)
> > > MCC Length 2
> > > 83 8d aa ...
> > > < ACL Data TX: Handle 75 flags 0x00 dlen 9 [hci0] 22.346681
> > > Channel: 65 len 5 [PSM 3 mode 0] {chan 1}
> > > RFCOMM(d): UIH
> > > Address : (0x81)
> > > CR Bit: 0
> > > DLCI : (0x20)
> > > Poll/FInal Bit : 1
> > > Length : 0
> > > FCS : (0x1e)
> > > Credits 33
> > > ---
> >
> > This is actually what I wanted to avoid, now you have to include all
> > the frames you changing instead of doing one by one. Btw, did you make
> > sure this is consistent with the spec and what we have done for L2CAP?
> >
> > > monitor/rfcomm.c | 21 +++++++++++++++++++++
> > > 1 file changed, 21 insertions(+)
> > >
> > > diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c index
> > > b85e8fd..10dc4e8 100644
> > > --- a/monitor/rfcomm.c
> > > +++ b/monitor/rfcomm.c
> > > @@ -90,48 +90,69 @@ static void print_rfcomm_hdr(const struct
> > l2cap_frame *frame,
> > > print_field("FCS : (0x%2.2x)", fcs); }
> > >
> > > +static void print_mcc(struct rfcomm_lmcc mcc) {
> > > + print_field("MCC Length %d", mcc.length); }
> > > +
> > > static inline void mcc_test(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > }
> > >
> > > static inline void mcc_fcon(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > }
> > >
> > > static inline void mcc_fcoff(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > }
> > >
> > > static inline void mcc_msc(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > packet_hexdump(frame->data, frame->size); }
> > >
> > > static inline void mcc_rpn(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > packet_hexdump(frame->data, frame->size); }
> > >
> > > static inline void mcc_rls(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > packet_hexdump(frame->data, frame->size); }
> > >
> > > static inline void mcc_pn(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > packet_hexdump(frame->data, frame->size); }
> > >
> > > static inline void mcc_nsc(const struct l2cap_frame *frame,
> > > struct rfcomm_lhdr hdr, struct
> > > rfcomm_lmcc mcc) {
> > > + print_rfcomm_hdr(frame, hdr);
> > > + print_mcc(mcc);
> > > packet_hexdump(frame->data, frame->size); }
> > >
> > > --
> > > 1.9.1
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe
> > > linux-bluetooth" in the body of a message to
> > > [email protected] More majordomo info at
> > > http://vger.kernel.org/majordomo-info.html
> >
> >
> >
> > --
> > Luiz Augusto von Dentz
>
> I have revisited the specs and came up with a modified below
> implementation.
>
> #ifdef HAVE_CONFIG_H
> #include <config.h>
> #endif
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <ctype.h>
> #include <inttypes.h>
>
> #include <bluetooth/bluetooth.h>
>
> #include "src/shared/util.h"
> #include "bt.h"
> #include "packet.h"
> #include "display.h"
> #include "l2cap.h"
> #include "uuid.h"
> #include "keys.h"
> #include "sdp.h"
> #include "rfcomm.h"
>
> #define GET_LEN8(length) ((length & 0xfe) >> 1) #define GET_LEN16(length)
> ((length & 0xfffe) >> 1)
>
> struct rfcomm_lhdr {
> uint8_t address;
> uint8_t control;
> uint16_t length;
> } __attribute__((packed));
>
> struct rfcomm_lmcc {
> uint8_t type;
> uint16_t length;
> } __attribute__((packed));
>
> struct rfcomm_data {
> uint8_t frame;
> const char *str;
> };
>
> static const struct rfcomm_data rfcomm_table[] = {
> { 0x2f, "Set Async Balance Mode (SABM) "},
> { 0x63, "Unnumbered Ack (UA)"},
> { 0x0f, "Disconnect Mode (DM)"},
> { 0x43, "Disconnect (DISC)"},
> { 0xef, "Header Check (UIH)"},
> { }
> };
> void rfcomm_packet(const struct l2cap_frame *frame) {
> uint8_t ctype, length, ex_length;
> const char *frame_str, *frame_color;
> int i;
> struct l2cap_frame rfcomm_frame;
> struct rfcomm_lhdr hdr;
> const struct rfcomm_data *rfcomm_data = NULL;
>
> l2cap_frame_pull(&rfcomm_frame, frame, 0);
>
> if (!l2cap_frame_get_u8(&rfcomm_frame, &hdr.address) ||
> !l2cap_frame_get_u8(&rfcomm_frame,
> &hdr.control) ||
> !l2cap_frame_get_u8(&rfcomm_frame, &length)){
> print_text(COLOR_ERROR, "Frame too short");
> packet_hexdump(frame->data, frame->size);
> return;
> }
>
> /* length maybe 1 or 2 octets */
> if (RFCOMM_TEST_EA(length))
> hdr.length = (uint16_t) GET_LEN8(length);
> else {
> if (!l2cap_frame_get_u8(&rfcomm_frame, &ex_length)) {
> print_text(COLOR_ERROR, "Frame too short");
> packet_hexdump(frame->data, frame->size);
> return;
> }
> hdr.length = ((uint16_t)length << 8) | ex_length;
> hdr.length = GET_LEN16(hdr.length);
> }
>
> ctype = RFCOMM_GET_TYPE(hdr.control);
>
> for (i = 0; rfcomm_table[i].str; i++) {
> if (rfcomm_table[i].frame == ctype) {
> rfcomm_data = &rfcomm_table[i];
> break;
> }
> }
>
> if (rfcomm_data) {
> if (frame->in)
> frame_color = COLOR_MAGENTA;
> else
> frame_color = COLOR_BLUE;
> frame_str = rfcomm_data->str;
> } else {
> frame_color = COLOR_WHITE_BG;
> frame_str = "Unknown";
> }
>
> if (!rfcomm_data) {
> packet_hexdump(frame->data, frame->size);
> return;
> }
>
> print_indent(6, frame_color, "RFCOMM: ", frame_str, COLOR_OFF,
> "(0x%2.2x)", ctype);
>
> /* Common print header function call */
>
> /* UIH frame handling function call */
>
> packet_hexdump(frame->data, frame->size); }
>
> Is it fine, for at least initial RFCOMM skeleton ?
> If its ok, then I will keep this as my initial patches and work on the further
> implementation.
> Here I am printing the logs as soon as pulling the data from l2cap_frame.
>
> Regards,
> Gowtham
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected] More majordomo
> info at http://vger.kernel.org/majordomo-info.html
I have incorporated the review comments and submitted the new patch set.
Regards,
Gowtham
Hi,
> -----Original Message-----
> From: Luiz Augusto von Dentz [mailto:[email protected]]
> Sent: Tuesday, November 04, 2014 5:46 PM
> To: Gowtham Anandha Babu
> Cc: [email protected]; Dmitry Kasatkin; Bharat Panda;
> [email protected]
> Subject: Re: [PATCH v2 6/6] monitor/rfcomm: Add mcc type handlers code
>
> Hi,
>
> On Mon, Nov 3, 2014 at 5:25 PM, Gowtham Anandha Babu
> <[email protected]> wrote:
> > From: Bharat Panda <[email protected]>
> >
> > Adds different mcc type handlers code to print in btmon.
> > ---
> > Below provided is the btmon rfcomm logs.
> >> ACL Data RX: Handle 75 flags 0x02 dlen 8 [hci0] 22.280283
> > Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
> > RFCOMM(s): SABM
> > Address : (0x83)
> > CR Bit: 1
> > DLCI : (0x20)
> > Poll/FInal Bit : 1
> > Length : 0
> > FCS : (0xca)
> > < ACL Data TX: Handle 75 flags 0x00 dlen 8 [hci0] 22.317803
> > Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
> > RFCOMM(s): UA
> > Address : (0x83)
> > CR Bit: 1
> > DLCI : (0x20)
> > Poll/FInal Bit : 1
> > Length : 0
> > FCS : (0x01)
> > < ACL Data TX: Handle 75 flags 0x00 dlen 12 [hci0] 22.317822
> > Channel: 65 len 8 [PSM 3 mode 0] {chan 1}
> > RFCOMM(s): MSC CMD
> > Address : (0x01)
> > CR Bit: 0
> > DLCI : (0x00)
> > Poll/FInal Bit : 0
> > Length : 4
> > FCS : (0xaa)
> > MCC Length 2
> > 83 8d aa ...
> > < ACL Data TX: Handle 75 flags 0x00 dlen 9 [hci0] 22.346681
> > Channel: 65 len 5 [PSM 3 mode 0] {chan 1}
> > RFCOMM(d): UIH
> > Address : (0x81)
> > CR Bit: 0
> > DLCI : (0x20)
> > Poll/FInal Bit : 1
> > Length : 0
> > FCS : (0x1e)
> > Credits 33
> > ---
>
> This is actually what I wanted to avoid, now you have to include all the frames
> you changing instead of doing one by one. Btw, did you make sure this is
> consistent with the spec and what we have done for L2CAP?
>
> > monitor/rfcomm.c | 21 +++++++++++++++++++++
> > 1 file changed, 21 insertions(+)
> >
> > diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c index
> > b85e8fd..10dc4e8 100644
> > --- a/monitor/rfcomm.c
> > +++ b/monitor/rfcomm.c
> > @@ -90,48 +90,69 @@ static void print_rfcomm_hdr(const struct
> l2cap_frame *frame,
> > print_field("FCS : (0x%2.2x)", fcs); }
> >
> > +static void print_mcc(struct rfcomm_lmcc mcc) {
> > + print_field("MCC Length %d", mcc.length); }
> > +
> > static inline void mcc_test(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > }
> >
> > static inline void mcc_fcon(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > }
> >
> > static inline void mcc_fcoff(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > }
> >
> > static inline void mcc_msc(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > packet_hexdump(frame->data, frame->size); }
> >
> > static inline void mcc_rpn(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > packet_hexdump(frame->data, frame->size); }
> >
> > static inline void mcc_rls(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > packet_hexdump(frame->data, frame->size); }
> >
> > static inline void mcc_pn(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > packet_hexdump(frame->data, frame->size); }
> >
> > static inline void mcc_nsc(const struct l2cap_frame *frame,
> > struct rfcomm_lhdr hdr, struct
> > rfcomm_lmcc mcc) {
> > + print_rfcomm_hdr(frame, hdr);
> > + print_mcc(mcc);
> > packet_hexdump(frame->data, frame->size); }
> >
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe
> > linux-bluetooth" in the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> Luiz Augusto von Dentz
I have revisited the specs and came up with a modified below implementation.
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
#include <bluetooth/bluetooth.h>
#include "src/shared/util.h"
#include "bt.h"
#include "packet.h"
#include "display.h"
#include "l2cap.h"
#include "uuid.h"
#include "keys.h"
#include "sdp.h"
#include "rfcomm.h"
#define GET_LEN8(length) ((length & 0xfe) >> 1)
#define GET_LEN16(length) ((length & 0xfffe) >> 1)
struct rfcomm_lhdr {
uint8_t address;
uint8_t control;
uint16_t length;
} __attribute__((packed));
struct rfcomm_lmcc {
uint8_t type;
uint16_t length;
} __attribute__((packed));
struct rfcomm_data {
uint8_t frame;
const char *str;
};
static const struct rfcomm_data rfcomm_table[] = {
{ 0x2f, "Set Async Balance Mode (SABM) "},
{ 0x63, "Unnumbered Ack (UA)"},
{ 0x0f, "Disconnect Mode (DM)"},
{ 0x43, "Disconnect (DISC)"},
{ 0xef, "Header Check (UIH)"},
{ }
};
void rfcomm_packet(const struct l2cap_frame *frame)
{
uint8_t ctype, length, ex_length;
const char *frame_str, *frame_color;
int i;
struct l2cap_frame rfcomm_frame;
struct rfcomm_lhdr hdr;
const struct rfcomm_data *rfcomm_data = NULL;
l2cap_frame_pull(&rfcomm_frame, frame, 0);
if (!l2cap_frame_get_u8(&rfcomm_frame, &hdr.address) ||
!l2cap_frame_get_u8(&rfcomm_frame, &hdr.control) ||
!l2cap_frame_get_u8(&rfcomm_frame, &length)){
print_text(COLOR_ERROR, "Frame too short");
packet_hexdump(frame->data, frame->size);
return;
}
/* length maybe 1 or 2 octets */
if (RFCOMM_TEST_EA(length))
hdr.length = (uint16_t) GET_LEN8(length);
else {
if (!l2cap_frame_get_u8(&rfcomm_frame, &ex_length)) {
print_text(COLOR_ERROR, "Frame too short");
packet_hexdump(frame->data, frame->size);
return;
}
hdr.length = ((uint16_t)length << 8) | ex_length;
hdr.length = GET_LEN16(hdr.length);
}
ctype = RFCOMM_GET_TYPE(hdr.control);
for (i = 0; rfcomm_table[i].str; i++) {
if (rfcomm_table[i].frame == ctype) {
rfcomm_data = &rfcomm_table[i];
break;
}
}
if (rfcomm_data) {
if (frame->in)
frame_color = COLOR_MAGENTA;
else
frame_color = COLOR_BLUE;
frame_str = rfcomm_data->str;
} else {
frame_color = COLOR_WHITE_BG;
frame_str = "Unknown";
}
if (!rfcomm_data) {
packet_hexdump(frame->data, frame->size);
return;
}
print_indent(6, frame_color, "RFCOMM: ", frame_str, COLOR_OFF,
"(0x%2.2x)", ctype);
/* Common print header function call */
/* UIH frame handling function call */
packet_hexdump(frame->data, frame->size);
}
Is it fine, for at least initial RFCOMM skeleton ?
If its ok, then I will keep this as my initial patches and work on the further implementation.
Here I am printing the logs as soon as pulling the data from l2cap_frame.
Regards,
Gowtham
Hi,
On Mon, Nov 3, 2014 at 5:25 PM, Gowtham Anandha Babu
<[email protected]> wrote:
> From: Bharat Panda <[email protected]>
>
> Adds different mcc type handlers code to print in btmon.
> ---
> Below provided is the btmon rfcomm logs.
>> ACL Data RX: Handle 75 flags 0x02 dlen 8 [hci0] 22.280283
> Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
> RFCOMM(s): SABM
> Address : (0x83)
> CR Bit: 1
> DLCI : (0x20)
> Poll/FInal Bit : 1
> Length : 0
> FCS : (0xca)
> < ACL Data TX: Handle 75 flags 0x00 dlen 8 [hci0] 22.317803
> Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
> RFCOMM(s): UA
> Address : (0x83)
> CR Bit: 1
> DLCI : (0x20)
> Poll/FInal Bit : 1
> Length : 0
> FCS : (0x01)
> < ACL Data TX: Handle 75 flags 0x00 dlen 12 [hci0] 22.317822
> Channel: 65 len 8 [PSM 3 mode 0] {chan 1}
> RFCOMM(s): MSC CMD
> Address : (0x01)
> CR Bit: 0
> DLCI : (0x00)
> Poll/FInal Bit : 0
> Length : 4
> FCS : (0xaa)
> MCC Length 2
> 83 8d aa ...
> < ACL Data TX: Handle 75 flags 0x00 dlen 9 [hci0] 22.346681
> Channel: 65 len 5 [PSM 3 mode 0] {chan 1}
> RFCOMM(d): UIH
> Address : (0x81)
> CR Bit: 0
> DLCI : (0x20)
> Poll/FInal Bit : 1
> Length : 0
> FCS : (0x1e)
> Credits 33
> ---
This is actually what I wanted to avoid, now you have to include all
the frames you changing instead of doing one by one. Btw, did you make
sure this is consistent with the spec and what we have done for L2CAP?
> monitor/rfcomm.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
> index b85e8fd..10dc4e8 100644
> --- a/monitor/rfcomm.c
> +++ b/monitor/rfcomm.c
> @@ -90,48 +90,69 @@ static void print_rfcomm_hdr(const struct l2cap_frame *frame,
> print_field("FCS : (0x%2.2x)", fcs);
> }
>
> +static void print_mcc(struct rfcomm_lmcc mcc)
> +{
> + print_field("MCC Length %d", mcc.length);
> +}
> +
> static inline void mcc_test(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> }
>
> static inline void mcc_fcon(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> }
>
> static inline void mcc_fcoff(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> }
>
> static inline void mcc_msc(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> packet_hexdump(frame->data, frame->size);
> }
>
> static inline void mcc_rpn(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> packet_hexdump(frame->data, frame->size);
> }
>
> static inline void mcc_rls(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> packet_hexdump(frame->data, frame->size);
> }
>
> static inline void mcc_pn(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> packet_hexdump(frame->data, frame->size);
> }
>
> static inline void mcc_nsc(const struct l2cap_frame *frame,
> struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
> {
> + print_rfcomm_hdr(frame, hdr);
> + print_mcc(mcc);
> packet_hexdump(frame->data, frame->size);
> }
>
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Luiz Augusto von Dentz
From: Bharat Panda <[email protected]>
Adds different mcc type handlers code to print in btmon.
---
Below provided is the btmon rfcomm logs.
> ACL Data RX: Handle 75 flags 0x02 dlen 8 [hci0] 22.280283
Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
RFCOMM(s): SABM
Address : (0x83)
CR Bit: 1
DLCI : (0x20)
Poll/FInal Bit : 1
Length : 0
FCS : (0xca)
< ACL Data TX: Handle 75 flags 0x00 dlen 8 [hci0] 22.317803
Channel: 65 len 4 [PSM 3 mode 0] {chan 1}
RFCOMM(s): UA
Address : (0x83)
CR Bit: 1
DLCI : (0x20)
Poll/FInal Bit : 1
Length : 0
FCS : (0x01)
< ACL Data TX: Handle 75 flags 0x00 dlen 12 [hci0] 22.317822
Channel: 65 len 8 [PSM 3 mode 0] {chan 1}
RFCOMM(s): MSC CMD
Address : (0x01)
CR Bit: 0
DLCI : (0x00)
Poll/FInal Bit : 0
Length : 4
FCS : (0xaa)
MCC Length 2
83 8d aa ...
< ACL Data TX: Handle 75 flags 0x00 dlen 9 [hci0] 22.346681
Channel: 65 len 5 [PSM 3 mode 0] {chan 1}
RFCOMM(d): UIH
Address : (0x81)
CR Bit: 0
DLCI : (0x20)
Poll/FInal Bit : 1
Length : 0
FCS : (0x1e)
Credits 33
---
monitor/rfcomm.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
index b85e8fd..10dc4e8 100644
--- a/monitor/rfcomm.c
+++ b/monitor/rfcomm.c
@@ -90,48 +90,69 @@ static void print_rfcomm_hdr(const struct l2cap_frame *frame,
print_field("FCS : (0x%2.2x)", fcs);
}
+static void print_mcc(struct rfcomm_lmcc mcc)
+{
+ print_field("MCC Length %d", mcc.length);
+}
+
static inline void mcc_test(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
}
static inline void mcc_fcon(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
}
static inline void mcc_fcoff(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
}
static inline void mcc_msc(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
packet_hexdump(frame->data, frame->size);
}
static inline void mcc_rpn(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
packet_hexdump(frame->data, frame->size);
}
static inline void mcc_rls(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
packet_hexdump(frame->data, frame->size);
}
static inline void mcc_pn(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
packet_hexdump(frame->data, frame->size);
}
static inline void mcc_nsc(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
{
+ print_rfcomm_hdr(frame, hdr);
+ print_mcc(mcc);
packet_hexdump(frame->data, frame->size);
}
--
1.9.1
From: Bharat Panda <[email protected]>
Changes made to decode different mcc frame type in RFCOMM
---
monitor/rfcomm.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 2 deletions(-)
diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
index a43b2a2..b85e8fd 100644
--- a/monitor/rfcomm.c
+++ b/monitor/rfcomm.c
@@ -90,6 +90,51 @@ static void print_rfcomm_hdr(const struct l2cap_frame *frame,
print_field("FCS : (0x%2.2x)", fcs);
}
+static inline void mcc_test(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+}
+
+static inline void mcc_fcon(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+}
+
+static inline void mcc_fcoff(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+}
+
+static inline void mcc_msc(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+ packet_hexdump(frame->data, frame->size);
+}
+
+static inline void mcc_rpn(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+ packet_hexdump(frame->data, frame->size);
+}
+
+static inline void mcc_rls(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+ packet_hexdump(frame->data, frame->size);
+}
+
+static inline void mcc_pn(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+ packet_hexdump(frame->data, frame->size);
+}
+
+static inline void mcc_nsc(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr, struct rfcomm_lmcc mcc)
+{
+ packet_hexdump(frame->data, frame->size);
+}
+
static const char *type2str(uint8_t type)
{
switch (type) {
@@ -141,8 +186,37 @@ static inline bool mcc_frame(const struct l2cap_frame *frame,
print_indent(7, opcode_color, "RFCOMM(s): ", "", COLOR_OFF, "%s %s",
type2str(type), CR_STR(mcc.type));
- print_rfcomm_hdr(&rfcomm_frame, hdr);
- packet_hexdump(rfcomm_frame.data, rfcomm_frame.size);
+ switch (type) {
+ case RFCOMM_TEST:
+ mcc_test(&rfcomm_frame, hdr, mcc);
+ packet_hexdump(rfcomm_frame.data, rfcomm_frame.size);
+ break;
+ case RFCOMM_FCON:
+ mcc_fcon(&rfcomm_frame, hdr, mcc);
+ break;
+ case RFCOMM_FCOFF:
+ mcc_fcoff(&rfcomm_frame, hdr, mcc);
+ break;
+ case RFCOMM_MSC:
+ mcc_msc(&rfcomm_frame, hdr, mcc);
+ break;
+ case RFCOMM_RPN:
+ mcc_rpn(&rfcomm_frame, hdr, mcc);
+ break;
+ case RFCOMM_RLS:
+ mcc_rls(&rfcomm_frame, hdr, mcc);
+ break;
+ case RFCOMM_PN:
+ mcc_pn(&rfcomm_frame, hdr, mcc);
+ break;
+ case RFCOMM_NSC:
+ mcc_nsc(&rfcomm_frame, hdr, mcc);
+ break;
+ default:
+ print_field("MCC message type 0x%02x: ", type);
+ print_rfcomm_hdr(&rfcomm_frame, hdr);
+ packet_hexdump(rfcomm_frame.data, rfcomm_frame.size);
+ }
return true;
}
--
1.9.1
Changes made to decode MCC frame in RFCOMM for btmon.
---
monitor/rfcomm.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 1 deletion(-)
diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
index 6994ffd..a43b2a2 100644
--- a/monitor/rfcomm.c
+++ b/monitor/rfcomm.c
@@ -44,8 +44,15 @@
#include "sdp.h"
#include "rfcomm.h"
+static char *cr_str[] = {
+ "RSP",
+ "CMD"
+};
+
+#define CR_STR(type) cr_str[GET_CR(type)]
#define GET_LEN8(length) ((length & 0xfe) >> 1)
#define GET_LEN16(length) ((length & 0xfffe) >> 1)
+#define GET_CR(type) ((type & 0x02) >> 1)
#define GET_PF(ctr) (((ctr) >> 4) & 0x1)
struct rfcomm_lhdr {
@@ -54,17 +61,89 @@ struct rfcomm_lhdr {
uint16_t length;
} __attribute__((packed));
+struct rfcomm_lmcc {
+ uint8_t type;
+ uint16_t length;
+} __attribute__((packed));
+
+
const char *opcode_color;
static void print_rfcomm_hdr(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr)
{
+ uint8_t pf, dlci, fcs, cr, ilen;
+ const void *ptr;
+
+ dlci = RFCOMM_GET_DLCI(hdr.address);
+ pf = GET_PF(hdr.control);
+ cr = GET_CR(hdr.address);
+ ilen = hdr.length;
+ ptr = (frame->data)+frame->size-1;
+ fcs = *(uint8_t *)(ptr);
+
+ print_field("Address : (0x%2.2x)", hdr.address);
+ print_field("CR Bit: %d", cr);
+ print_field("DLCI : (0x%2.2x)", dlci);
+ print_field("Poll/FInal Bit : %d", pf);
+ print_field("Length : %d", ilen);
+ print_field("FCS : (0x%2.2x)", fcs);
+}
+
+static const char *type2str(uint8_t type)
+{
+ switch (type) {
+ case RFCOMM_TEST:
+ return "TEST";
+ case RFCOMM_FCON:
+ return "FCON";
+ case RFCOMM_FCOFF:
+ return "FCOFF";
+ case RFCOMM_MSC:
+ return "MSC";
+ case RFCOMM_RPN:
+ return "RPN";
+ case RFCOMM_RLS:
+ return "RLS";
+ case RFCOMM_PN:
+ return "PN";
+ case RFCOMM_NSC:
+ return "NSC";
+ default:
+ return "Unknown";
+ }
}
static inline bool mcc_frame(const struct l2cap_frame *frame,
struct rfcomm_lhdr hdr)
{
- packet_hexdump(frame->data, frame->size);
+ uint8_t length, ex_length, type;
+ struct l2cap_frame rfcomm_frame;
+ struct rfcomm_lmcc mcc;
+
+ l2cap_frame_pull(&rfcomm_frame, frame, 0);
+
+ if (!l2cap_frame_get_u8(&rfcomm_frame, &mcc.type) ||
+ !l2cap_frame_get_u8(&rfcomm_frame, &length))
+ return false;
+
+ if (RFCOMM_TEST_EA(length))
+ mcc.length = (uint16_t) GET_LEN8(length);
+ else {
+ if (!l2cap_frame_get_u8(&rfcomm_frame, &ex_length))
+ return false;
+ mcc.length = ((uint16_t) length << 8) | ex_length;
+ mcc.length = GET_LEN16(hdr.length);
+ }
+
+ type = RFCOMM_GET_MCC_TYPE(mcc.type);
+
+ print_indent(7, opcode_color, "RFCOMM(s): ", "", COLOR_OFF, "%s %s",
+ type2str(type), CR_STR(mcc.type));
+
+ print_rfcomm_hdr(&rfcomm_frame, hdr);
+ packet_hexdump(rfcomm_frame.data, rfcomm_frame.size);
+
return true;
}
--
1.9.1
Changes made to decode UIH frame in btmon.
---
monitor/rfcomm.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
index 395a7b8..6994ffd 100644
--- a/monitor/rfcomm.c
+++ b/monitor/rfcomm.c
@@ -46,6 +46,7 @@
#define GET_LEN8(length) ((length & 0xfe) >> 1)
#define GET_LEN16(length) ((length & 0xfffe) >> 1)
+#define GET_PF(ctr) (((ctr) >> 4) & 0x1)
struct rfcomm_lhdr {
uint8_t address;
@@ -60,8 +61,36 @@ static void print_rfcomm_hdr(const struct l2cap_frame *frame,
{
}
+static inline bool mcc_frame(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr)
+{
+ packet_hexdump(frame->data, frame->size);
+ return true;
+}
+
static bool uih_frame(const struct l2cap_frame *frame, struct rfcomm_lhdr hdr)
{
+ uint8_t credits;
+
+ struct l2cap_frame rfcomm_frame;
+
+ l2cap_frame_pull(&rfcomm_frame, frame, 0);
+
+ if (!RFCOMM_GET_CHANNEL(hdr.address)) {
+ return mcc_frame(&rfcomm_frame, hdr);
+ } else {
+ print_indent(7, opcode_color, "RFCOMM(d): UIH ", "",
+ COLOR_OFF, "");
+ print_rfcomm_hdr(&rfcomm_frame, hdr);
+ if (GET_PF(hdr.control)) {
+ if (!l2cap_frame_get_u8(&rfcomm_frame, &credits))
+ return false;
+ print_field("Credits %d", credits);
+ return true;
+ }
+ }
+
+ packet_hexdump(rfcomm_frame.data, rfcomm_frame.size);
return true;
}
--
1.9.1
Changes made to decode RFCOMM specific commands in btmon.
---
monitor/rfcomm.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)
diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
index 8b7e8ce..395a7b8 100644
--- a/monitor/rfcomm.c
+++ b/monitor/rfcomm.c
@@ -44,18 +44,87 @@
#include "sdp.h"
#include "rfcomm.h"
+#define GET_LEN8(length) ((length & 0xfe) >> 1)
+#define GET_LEN16(length) ((length & 0xfffe) >> 1)
+
+struct rfcomm_lhdr {
+ uint8_t address;
+ uint8_t control;
+ uint16_t length;
+} __attribute__((packed));
+
const char *opcode_color;
+static void print_rfcomm_hdr(const struct l2cap_frame *frame,
+ struct rfcomm_lhdr hdr)
+{
+}
+
+static bool uih_frame(const struct l2cap_frame *frame, struct rfcomm_lhdr hdr)
+{
+ return true;
+}
+
void rfcomm_packet(const struct l2cap_frame *frame)
{
+ uint8_t ctr_type, length, ex_length;
+ const char *opcode_str;
+ struct rfcomm_lhdr hdr;
+ struct l2cap_frame rfcomm_frame;
+
+ l2cap_frame_pull(&rfcomm_frame, frame, 0);
+
+ if (!l2cap_frame_get_u8(&rfcomm_frame, &hdr.address) ||
+ !l2cap_frame_get_u8(&rfcomm_frame, &hdr.control) ||
+ !l2cap_frame_get_u8(&rfcomm_frame, &length))
+ goto fail;
+
+ if (RFCOMM_TEST_EA(length))
+ hdr.length = (uint16_t) GET_LEN8(length);
+ else {
+ if (!l2cap_frame_get_u8(&rfcomm_frame, &ex_length))
+ goto fail;
+ hdr.length = ((uint16_t)length << 8) | ex_length;
+ hdr.length = GET_LEN16(hdr.length);
+ }
+
if (frame->in)
opcode_color = COLOR_MAGENTA;
else
opcode_color = COLOR_BLUE;
- print_indent(7, opcode_color, "RFCOMM: ", "",
- COLOR_OFF, "");
+ ctr_type = RFCOMM_GET_TYPE(hdr.control);
+
+ if (ctr_type == RFCOMM_UIH) {
+ if (uih_frame(&rfcomm_frame, hdr))
+ return;
+ goto fail;
+ } else {
+ switch (ctr_type) {
+ case RFCOMM_SABM:
+ opcode_str = "SABM";
+ break;
+ case RFCOMM_UA:
+ opcode_str = "UA";
+ break;
+ case RFCOMM_DM:
+ opcode_str = "DM";
+ break;
+ case RFCOMM_DISC:
+ opcode_str = "DISC";
+ break;
+ default:
+ opcode_str = "ERR";
+ }
+
+ print_indent(7, opcode_color, "RFCOMM(s): ", opcode_str,
+ COLOR_OFF, "");
+ print_rfcomm_hdr(&rfcomm_frame, hdr);
+ return;
+ }
+fail:
+ print_text(COLOR_ERROR, "Frame too short");
packet_hexdump(frame->data, frame->size);
return;
}
--
1.9.1
Changes made to add initial code to support RFCOMM frame in btmon
---
Makefile.tools | 1 +
android/Android.mk | 1 +
monitor/l2cap.c | 4 ++++
monitor/l2cap.h | 1 +
monitor/rfcomm.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 68 insertions(+)
create mode 100644 monitor/rfcomm.c
diff --git a/Makefile.tools b/Makefile.tools
index 42cccc6..75a6faa 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -26,6 +26,7 @@ monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
monitor/l2cap.h monitor/l2cap.c \
monitor/sdp.h monitor/sdp.c \
monitor/avctp.h monitor/avctp.c \
+ monitor/rfcomm.h monitor/rfcomm.c \
monitor/uuid.h monitor/uuid.c \
monitor/hwdb.h monitor/hwdb.c \
monitor/keys.h monitor/keys.c \
diff --git a/android/Android.mk b/android/Android.mk
index aefe41c..eebd863 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -289,6 +289,7 @@ LOCAL_SRC_FILES := \
bluez/monitor/packet.c \
bluez/monitor/l2cap.c \
bluez/monitor/avctp.c \
+ bluez/monitor/rfcomm.c \
bluez/monitor/uuid.c \
bluez/monitor/sdp.c \
bluez/monitor/vendor.c \
diff --git a/monitor/l2cap.c b/monitor/l2cap.c
index c004d6b..ebdd20f 100644
--- a/monitor/l2cap.c
+++ b/monitor/l2cap.c
@@ -42,6 +42,7 @@
#include "keys.h"
#include "sdp.h"
#include "avctp.h"
+#include "rfcomm.h"
#define MAX_CHAN 64
@@ -2643,6 +2644,9 @@ static void l2cap_frame(uint16_t index, bool in, uint16_t handle,
case 0x0001:
sdp_packet(&frame);
break;
+ case 0x0003:
+ rfcomm_packet(&frame);
+ break;
case 0x001f:
att_packet(index, in, handle, cid, data, size);
break;
diff --git a/monitor/l2cap.h b/monitor/l2cap.h
index 5faaea6..1f70b68 100644
--- a/monitor/l2cap.h
+++ b/monitor/l2cap.h
@@ -153,3 +153,4 @@ static inline bool l2cap_frame_get_le64(struct l2cap_frame *frame,
void l2cap_packet(uint16_t index, bool in, uint16_t handle, uint8_t flags,
const void *data, uint16_t size);
+void rfcomm_packet(const struct l2cap_frame *frame);
diff --git a/monitor/rfcomm.c b/monitor/rfcomm.c
new file mode 100644
index 0000000..8b7e8ce
--- /dev/null
+++ b/monitor/rfcomm.c
@@ -0,0 +1,61 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011-2014 Intel Corporation
+ * Copyright (C) 2002-2010 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include <bluetooth/bluetooth.h>
+
+#include "src/shared/util.h"
+#include "bt.h"
+#include "packet.h"
+#include "display.h"
+#include "l2cap.h"
+#include "uuid.h"
+#include "keys.h"
+#include "sdp.h"
+#include "rfcomm.h"
+
+const char *opcode_color;
+
+void rfcomm_packet(const struct l2cap_frame *frame)
+{
+ if (frame->in)
+ opcode_color = COLOR_MAGENTA;
+ else
+ opcode_color = COLOR_BLUE;
+
+ print_indent(7, opcode_color, "RFCOMM: ", "",
+ COLOR_OFF, "");
+
+ packet_hexdump(frame->data, frame->size);
+ return;
+}
--
1.9.1