This allows hcidump to parse the FCS and other options that are used to
negotiate an Enhanced Retransmission or Streaming mode L2CAP connection.
I've add an #indef L2CAP_CONF_FCS to the top of the code which mirrors
a change under the kernel headers to allow building on systems without
the modified kernel headers.
---
l2cap.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/parser/l2cap.c b/parser/l2cap.c
index a906f42..64839f5 100644
--- a/parser/l2cap.c
+++ b/parser/l2cap.c
@@ -65,6 +65,10 @@ static cid_info cid_table[2][CID_TABLE_SIZE];
#define SCID cid_table[0]
#define DCID cid_table[1]
+#ifndef L2CAP_CONF_FCS
+#define L2CAP_CONF_FCS 0x05
+#endif
+
static struct frame *add_handle(uint16_t handle)
{
register handle_info *t = handle_table;
@@ -306,6 +310,10 @@ static char *mode2str(uint8_t mode)
return "Retransmission";
case 0x02:
return "Flow control";
+ case 0x03:
+ return "Enhanced Retransmission";
+ case 0x04:
+ return "Streaming";
default:
return "Reserved";
}
@@ -428,7 +436,7 @@ static void conf_rfc(void *ptr, int len, int in,
uint16_t cid)
set_mode(in, cid, mode);
printf("RFC 0x%02x (%s", mode, mode2str(mode));
- if (mode == 0x01 || mode == 0x02) {
+ if (mode >= 0x01 && mode <= 0x08) {
uint8_t txwin, maxtrans;
uint16_t rto, mto, mps;
txwin = *((uint8_t *) (ptr + 1));
@@ -478,6 +486,12 @@ static void conf_opt(int level, void *ptr, int len,
int in, uint16_t cid)
conf_rfc(h->val, h->len, in, cid);
break;
+ case L2CAP_CONF_FCS:
+ printf("FCS Option");
+ if (h->len > 0);
+ printf(" 0x%x", get_val(h->val, h->len));
+ break;
+
default:
printf("Unknown (type %2.2x, len %d)", h->type & 0x7f, h->len);
break;
@@ -510,6 +524,9 @@ static void conf_list(int level, uint8_t *list, int
len)
case L2CAP_CONF_RFC:
printf("RFC ");
break;
+ case L2CAP_CONF_FCS:
+ printf("FCS Option");
+ break;
default:
printf("%2.2x ", list[i] & 0x7f);
break;
This allows hcidump to parse the FCS and other options that are used to
negotiate an Enhanced Retransmission or Streaming mode L2CAP connection.
When receiving the MTU option, don't set the mode to Basic.
This patch depends upon headers from libbluetooth which define the
constant L2CAP_CONF_FCS.
---
l2cap.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 63 insertions(+), 3 deletions(-)
diff --git a/parser/l2cap.c b/parser/l2cap.c
index a906f42..6286236 100644
--- a/parser/l2cap.c
+++ b/parser/l2cap.c
@@ -56,6 +56,7 @@ typedef struct {
uint16_t cid;
uint16_t psm;
uint16_t num;
+ uint8_t fcs;
uint8_t mode;
} cid_info;
#define CID_TABLE_SIZE 20
@@ -108,6 +109,7 @@ static void add_cid(int in, uint16_t handle,
uint16_t cid, uint16_t psm)
table[pos].cid = cid;
table[pos].psm = psm;
table[pos].num = num;
+ table[pos].fcs = 0x01;
table[pos].mode = 0;
}
}
@@ -132,6 +134,7 @@ static void del_cid(int in, uint16_t dcid, uint16_t
scid)
cid_table[t][i].cid = 0;
cid_table[t][i].psm = 0;
cid_table[t][i].num = 0;
+ cid_table[t][i].fcs = 0;
cid_table[t][i].mode = 0;
break;
}
@@ -149,11 +152,34 @@ static void del_handle(uint16_t handle)
cid_table[t][i].cid = 0;
cid_table[t][i].psm = 0;
cid_table[t][i].num = 0;
+ cid_table[t][i].fcs = 0;
cid_table[t][i].mode = 0;
break;
}
}
}
+
+static void set_fcs(int in, uint16_t cid, uint8_t fcs)
+{
+ register cid_info *table = cid_table[in];
+ register int i;
+
+ for (i = 0; i < CID_TABLE_SIZE; i++)
+ if (table[i].cid == cid)
+ table[i].fcs = fcs;
+}
+
+static uint8_t get_fcs(int in, uint16_t cid)
+{
+ register cid_info *table = cid_table[in];
+ register int i;
+
+ for (i = 0; i < CID_TABLE_SIZE; i++)
+ if (table[i].cid == cid)
+ return table[i].fcs;
+ return 0x01;
+}
+
static uint16_t get_psm(int in, uint16_t cid)
{
register cid_info *table = cid_table[in];
@@ -271,6 +297,19 @@ static char *confresult2str(uint16_t result)
return "Reserved";
}
}
+
+static char *fcs2str(uint8_t fcs)
+{
+ switch (fcs) {
+ case 0x00:
+ return "No FCS";
+ case 0x01:
+ return "16-bit FCS";
+ default:
+ return "Reserved";
+ }
+}
+
static char *inforesult2str(uint16_t result)
{
switch (result) {
@@ -306,6 +345,10 @@ static char *mode2str(uint8_t mode)
return "Retransmission";
case 0x02:
return "Flow control";
+ case 0x03:
+ return "Enhanced Retransmission";
+ case 0x04:
+ return "Streaming";
default:
return "Reserved";
}
@@ -336,8 +379,9 @@ static char *supervisory2str(uint8_t supervisory)
case 0x01:
return "Reject (REJ)";
case 0x02:
+ return "Receiver Not Ready (RNR)";
case 0x03:
- return "Reserved Supervisory";
+ return "Select Reject (SREJ)";
default:
return "Bad Supervisory";
}
@@ -420,6 +464,16 @@ static inline void conn_rsp(int level, struct frame
*frm)
printf("\n");
}
+static void conf_fcs(void *ptr, int len, int in, uint16_t cid)
+{
+ uint8_t fcs;
+
+ fcs = *((uint8_t *) ptr);
+ set_fcs(in, cid, fcs);
+
+ printf("FCS Option 0x%02x (%s)", fcs, fcs2str(fcs));
+}
+
static void conf_rfc(void *ptr, int len, int in, uint16_t cid)
{
uint8_t mode;
@@ -428,7 +482,7 @@ static void conf_rfc(void *ptr, int len, int in,
uint16_t cid)
set_mode(in, cid, mode);
printf("RFC 0x%02x (%s", mode, mode2str(mode));
- if (mode == 0x01 || mode == 0x02) {
+ if (mode >= 0x01 && mode <= 0x08) {
uint8_t txwin, maxtrans;
uint16_t rto, mto, mps;
txwin = *((uint8_t *) (ptr + 1));
@@ -456,7 +510,6 @@ static void conf_opt(int level, void *ptr, int len,
int in, uint16_t cid)
switch (h->type & 0x7f) {
case L2CAP_CONF_MTU:
- set_mode(in, cid, 0x00);
printf("MTU");
if (h->len > 0)
printf(" %d", get_val(h->val, h->len));
@@ -478,6 +531,10 @@ static void conf_opt(int level, void *ptr, int len,
int in, uint16_t cid)
conf_rfc(h->val, h->len, in, cid);
break;
+ case L2CAP_CONF_FCS:
+ conf_fcs(h->val, h->len, in, cid);
+ break;
+
default:
printf("Unknown (type %2.2x, len %d)", h->type & 0x7f, h->len);
break;
@@ -510,6 +567,9 @@ static void conf_list(int level, uint8_t *list, int
len)
case L2CAP_CONF_RFC:
printf("RFC ");
break;
+ case L2CAP_CONF_FCS:
+ printf("FCS Option ");
+ break;
default:
printf("%2.2x ", list[i] & 0x7f);
break;
Hi Nathan,
> This allows hcidump to parse the FCS and other options that are used to
> negotiate an Enhanced Retransmission or Streaming mode L2CAP connection.
>
> I've add an #indef L2CAP_CONF_FCS to the top of the code which mirrors
> a change under the kernel headers to allow building on systems without
> the modified kernel headers.
this needs to be submitted against libbluetooth. I just added that value
to it.
> ---
> l2cap.c | 19 ++++++++++++++++++-
> 1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/parser/l2cap.c b/parser/l2cap.c
> index a906f42..64839f5 100644
> --- a/parser/l2cap.c
> +++ b/parser/l2cap.c
> @@ -65,6 +65,10 @@ static cid_info cid_table[2][CID_TABLE_SIZE];
> #define SCID cid_table[0]
> #define DCID cid_table[1]
>
> +#ifndef L2CAP_CONF_FCS
> +#define L2CAP_CONF_FCS 0x05
> +#endif
> +
> static struct frame *add_handle(uint16_t handle)
> {
> register handle_info *t = handle_table;
> @@ -306,6 +310,10 @@ static char *mode2str(uint8_t mode)
> return "Retransmission";
> case 0x02:
> return "Flow control";
> + case 0x03:
> + return "Enhanced Retransmission";
> + case 0x04:
> + return "Streaming";
> default:
> return "Reserved";
> }
> @@ -428,7 +436,7 @@ static void conf_rfc(void *ptr, int len, int in,
> uint16_t cid)
> set_mode(in, cid, mode);
>
> printf("RFC 0x%02x (%s", mode, mode2str(mode));
> - if (mode == 0x01 || mode == 0x02) {
> + if (mode >= 0x01 && mode <= 0x08) {
> uint8_t txwin, maxtrans;
> uint16_t rto, mto, mps;
> txwin = *((uint8_t *) (ptr + 1));
> @@ -478,6 +486,12 @@ static void conf_opt(int level, void *ptr, int len,
> int in, uint16_t cid)
> conf_rfc(h->val, h->len, in, cid);
> break;
>
> + case L2CAP_CONF_FCS:
> + printf("FCS Option");
> + if (h->len > 0);
> + printf(" 0x%x", get_val(h->val, h->len));
> + break;
> +
> default:
> printf("Unknown (type %2.2x, len %d)", h->type & 0x7f, h->len);
> break;
> @@ -510,6 +524,9 @@ static void conf_list(int level, uint8_t *list, int
> len)
> case L2CAP_CONF_RFC:
> printf("RFC ");
> break;
> + case L2CAP_CONF_FCS:
> + printf("FCS Option");
> + break;
please add proper parsing of FCS Option here. And of course if has to
have an extra " " at the end.
Regards
Marcel