linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] Add parsing of BT 3.0+HS signalling
@ 2011-10-21 23:29 Peter Krystad
  2011-10-21 23:29 ` [PATCH 1/4] Add parsing of L2CAP Create/Move Channel signals Peter Krystad
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Peter Krystad @ 2011-10-21 23:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andrei.emeltchenko, Peter Krystad

This patchset adds parsing and display of BT 3.0+HS signalling

Peter Krystad (4):
  Add parsing of L2CAP Create/Move Channel signals
  Add parsing of A2MP signals
  Add parsing of L2CAP Fixed Channel list
  Minor cleanup of indentation in output

 lib/amp.h       |  133 +++++++++++++++
 lib/l2cap.h     |   50 ++++++
 parser/hci.c    |   15 +-
 parser/l2cap.c  |  498 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 parser/parser.h |    1 +
 src/hcidump.c   |    1 +
 6 files changed, 693 insertions(+), 5 deletions(-)
 create mode 100644 lib/amp.h

-- 
1.7.7

--
Peter Krystad
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] Add parsing of L2CAP Create/Move Channel signals
  2011-10-21 23:29 [PATCH 0/4] Add parsing of BT 3.0+HS signalling Peter Krystad
@ 2011-10-21 23:29 ` Peter Krystad
  2011-10-22  7:21   ` Marcel Holtmann
  2011-10-21 23:30 ` [PATCH 2/4] Add parsing of A2MP signals Peter Krystad
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Peter Krystad @ 2011-10-21 23:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andrei.emeltchenko, Peter Krystad

Add parsing of L2CAP Create/Move Channel signalling.
Example output:

2011-10-18 16:09:47.810208 > ACL data: handle 39 flags 0x02 dlen 13
    L2CAP(s): Create req: psm 4097 scid 0x4201 id 17
2011-10-18 16:09:47.810269 < ACL data: handle 39 flags 0x00 dlen 16
    L2CAP(s): Create rsp: dcid 0x0040 scid 0x4201 result 1 status 0
2011-10-18 16:09:47.898308 < ACL data: handle 39 flags 0x00 dlen 16
    L2CAP(s): Create rsp: dcid 0x0040 scid 0x4201 result 0 status 0

....

2011-10-18 14:25:24.646869 > ACL data: handle 39 flags 0x02 dlen 11
    L2CAP(s): Move req: icid 0x4000 id 17
2011-10-18 14:25:24.646987 < ACL data: handle 39 flags 0x00 dlen 12
    L2CAP(s): Move rsp: icid 0x4000 result 1
2011-10-18 14:25:24.846873 < ACL data: handle 39 flags 0x00 dlen 12
    L2CAP(s): Move rsp: icid 0x4000 result 0
2011-10-18 14:25:25.041844 > ACL data: handle 39 flags 0x02 dlen 12
    L2CAP(s): Move cfm: icid 0x4000 result 0
2011-10-18 14:25:25.041945 < ACL data: handle 39 flags 0x00 dlen 10
    L2CAP(s): Move cfm rsp: icid 0x4000
---
 lib/l2cap.h    |   50 +++++++++++++++++++++++++++++
 parser/l2cap.c |   97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/lib/l2cap.h b/lib/l2cap.h
index 3880551..b970a6e 100644
--- a/lib/l2cap.h
+++ b/lib/l2cap.h
@@ -82,6 +82,12 @@ struct l2cap_conninfo {
 #define L2CAP_ECHO_RSP		0x09
 #define L2CAP_INFO_REQ		0x0a
 #define L2CAP_INFO_RSP		0x0b
+#define L2CAP_CREATE_REQ	0x0c
+#define L2CAP_CREATE_RSP	0x0d
+#define L2CAP_MOVE_REQ		0x0e
+#define L2CAP_MOVE_RSP		0x0f
+#define L2CAP_MOVE_CFM		0x10
+#define L2CAP_MOVE_CFM_RSP	0x11
 
 /* L2CAP extended feature mask */
 #define L2CAP_FEAT_FLOWCTL	0x00000001
@@ -270,6 +276,50 @@ typedef struct {
 #define L2CAP_IR_SUCCESS	0x0000
 #define L2CAP_IR_NOTSUPP	0x0001
 
+typedef struct {
+	uint16_t	psm;
+	uint16_t	scid;
+	uint8_t		id;
+} __attribute__ ((packed)) l2cap_create_req;
+#define L2CAP_CREATE_REQ_SIZE 5
+
+typedef struct {
+	uint16_t	dcid;
+	uint16_t	scid;
+	uint16_t	result;
+	uint16_t	status;
+} __attribute__ ((packed)) l2cap_create_rsp;
+#define L2CAP_CREATE_RSP_SIZE 8
+
+typedef struct {
+	uint16_t	icid;
+	uint8_t		id;
+} __attribute__ ((packed)) l2cap_move_req;
+#define L2CAP_MOVE_REQ_SIZE 3
+
+typedef struct {
+	uint16_t	icid;
+	uint16_t	result;
+} __attribute__ ((packed)) l2cap_move_rsp;
+#define L2CAP_MOVE_RSP_SIZE 4
+
+typedef struct {
+	uint16_t	icid;
+	uint16_t	result;
+} __attribute__ ((packed)) l2cap_move_cfm;
+#define L2CAP_MOVE_CFM_SIZE 4
+
+typedef struct {
+	uint16_t	icid;
+} __attribute__ ((packed)) l2cap_move_cfm_rsp;
+#define L2CAP_MOVE_CFM_RSP_SIZE 2
+
+/* info type */
+#define L2CAP_IT_CL_MTU		0x0001
+#define L2CAP_IT_FEAT_MASK	0x0002
+
+/* info result */
+#define L2CAP_IR_SUCCESS	0x0000
 #ifdef __cplusplus
 }
 #endif
diff --git a/parser/l2cap.c b/parser/l2cap.c
index 6a5a4b2..7547e8b 100644
--- a/parser/l2cap.c
+++ b/parser/l2cap.c
@@ -399,6 +399,7 @@ static char *supervisory2str(uint8_t supervisory)
 	}
 }
 
+
 static inline void command_rej(int level, struct frame *frm)
 {
 	l2cap_cmd_rej *h = frm->ptr;
@@ -850,6 +851,78 @@ static void l2cap_ctrl_parse(int level, struct frame *frm, uint32_t ctrl)
 		printf(" F-bit");
 }
 
+static inline void create_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm)
+{
+	l2cap_create_req *h = frm->ptr;
+	uint16_t psm = btohs(h->psm);
+	uint16_t scid = btohs(h->scid);
+
+	if (p_filter(FILT_L2CAP))
+		return;
+
+	printf("Create req: psm %d scid 0x%4.4x id %d\n", psm, scid, h->id);
+}
+
+static inline void create_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm)
+{
+	l2cap_create_rsp *h = frm->ptr;
+	uint16_t scid = btohs(h->scid);
+	uint16_t dcid = btohs(h->dcid);
+	uint16_t result = btohs(h->result);
+	uint16_t status = btohs(h->status);
+
+	if (p_filter(FILT_L2CAP))
+		return;
+
+	printf("Create rsp: dcid 0x%4.4x scid 0x%4.4x result %d status %d\n", dcid, scid, result, status);
+}
+
+static inline void move_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm)
+{
+	l2cap_move_req *h = frm->ptr;
+	uint16_t icid = btohs(h->icid);
+
+	if (p_filter(FILT_L2CAP))
+		return;
+
+	printf("Move req: icid 0x%4.4x id %d\n", icid, h->id);
+}
+
+static inline void move_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm)
+{
+	l2cap_move_rsp *h = frm->ptr;
+	uint16_t icid = btohs(h->icid);
+	uint16_t result = btohs(h->result);
+
+	if (p_filter(FILT_L2CAP))
+		return;
+
+	printf("Move rsp: icid 0x%4.4x result %d\n", icid, result);
+}
+
+static inline void move_cfm(int level, l2cap_cmd_hdr *cmd, struct frame *frm)
+{
+	l2cap_move_cfm *h = frm->ptr;
+	uint16_t icid = btohs(h->icid);
+	uint16_t result = btohs(h->result);
+
+	if (p_filter(FILT_L2CAP))
+		return;
+
+	printf("Move cfm: icid 0x%4.4x result %d\n", icid, result);
+}
+
+static inline void move_cfm_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm)
+{
+	l2cap_move_cfm_rsp *h = frm->ptr;
+	uint16_t icid = btohs(h->icid);
+
+	if (p_filter(FILT_L2CAP))
+		return;
+
+	printf("Move cfm rsp: icid 0x%4.4x\n", icid);
+}
+
 static void l2cap_parse(int level, struct frame *frm)
 {
 	l2cap_hdr *hdr = (void *)frm->ptr;
@@ -919,6 +992,30 @@ static void l2cap_parse(int level, struct frame *frm)
 				info_rsp(level, hdr, frm);
 				break;
 
+			case L2CAP_CREATE_REQ:
+				create_req(level, hdr, frm);
+				break;
+
+			case L2CAP_CREATE_RSP:
+				create_rsp(level, hdr, frm);
+				break;
+
+			case L2CAP_MOVE_REQ:
+				move_req(level, hdr, frm);
+				break;
+
+			case L2CAP_MOVE_RSP:
+				move_rsp(level, hdr, frm);
+				break;
+
+			case L2CAP_MOVE_CFM:
+				move_cfm(level, hdr, frm);
+				break;
+
+			case L2CAP_MOVE_CFM_RSP:
+				move_cfm_rsp(level, hdr, frm);
+				break;
+
 			default:
 				if (p_filter(FILT_L2CAP))
 					break;
-- 
1.7.7

--
Peter Krystad
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] Add parsing of A2MP signals
  2011-10-21 23:29 [PATCH 0/4] Add parsing of BT 3.0+HS signalling Peter Krystad
  2011-10-21 23:29 ` [PATCH 1/4] Add parsing of L2CAP Create/Move Channel signals Peter Krystad
@ 2011-10-21 23:30 ` Peter Krystad
  2011-10-24  7:34   ` Andrei Emeltchenko
  2011-10-26 13:33   ` Andrei Emeltchenko
  2011-10-21 23:30 ` [PATCH 3/4] Add parsing of L2CAP Fixed Channel list Peter Krystad
  2011-10-21 23:30 ` [PATCH 4/4] Minor cleanup of indentation in output Peter Krystad
  3 siblings, 2 replies; 10+ messages in thread
From: Peter Krystad @ 2011-10-21 23:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andrei.emeltchenko, Peter Krystad

Add parsing of A2MP signalling.
Example output:

2011-10-18 16:09:44.493202 > ACL data: handle 39 flags 0x02 dlen 16
    A2MP: Discover req: mtu/mps 670 mask: 0x0000
2011-10-18 16:09:44.493404 < ACL data: handle 39 flags 0x00 dlen 22
    A2MP: Discover rsp: mtu/mps 670 mask: 0x0000
      Controller list:
        id 0, type 0, status 0x01 (Bluetooth only)
        id 17, type 254, status 0x06 (Full capacity)
2011-10-18 16:09:44.697203 > ACL data: handle 39 flags 0x02 dlen 13
    A2MP: Get Info req: id 17
2011-10-18 16:09:44.697312 < ACL data: handle 39 flags 0x00 dlen 30
    A2MP: Get Info rsp: id 17 status (0) Success
      total bandwidth 500000
      max guaranteed bandwidth 0
      min latency 100000
      pal capabilities 0x0000
      assoc size 8
2011-10-18 16:09:44.893203 > ACL data: handle 39 flags 0x02 dlen 13
    A2MP: Get AMP Assoc req: id 17
2011-10-18 16:09:44.893618 < ACL data: handle 39 flags 0x00 dlen 22
    A2MP: Get AMP Assoc rsp: id 17 status (0) Success
      assoc data:
        08 01 b1 01 0a 04 6c 42
2011-10-18 16:09:45.598201 > ACL data: handle 39 flags 0x02 dlen 22
    A2MP: Create Physical Link req: local id 1 remote id 17
      assoc data:
        08 01 b1 01 0a 04 6d 38
2011-10-18 16:09:45.598643 < ACL data: handle 39 flags 0x00 dlen 15
    A2MP: Create Physical Link rsp: local id 17 remote id 1 status 0
      Success
---
 lib/amp.h       |  133 +++++++++++++++++++
 parser/l2cap.c  |  385 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 parser/parser.h |    1 +
 src/hcidump.c   |    1 +
 4 files changed, 520 insertions(+), 0 deletions(-)
 create mode 100644 lib/amp.h

diff --git a/lib/amp.h b/lib/amp.h
new file mode 100644
index 0000000..0c6300a
--- /dev/null
+++ b/lib/amp.h
@@ -0,0 +1,133 @@
+/*
+ *
+ *	BlueZ - Bluetooth protocol stack for Linux
+ *
+ *	Copyright (C) 2010-2011 Code Aurora Forum.  All rights reserved.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License version 2 and
+ *	only version 2 as published by the Free Software Foundation.
+ *
+ *	This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef __AMP_H
+#define __AMP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AMP_MGR_CID 0x03
+
+/* AMP manager codes */
+#define AMP_COMMAND_REJ		0x01
+#define AMP_DISCOVER_REQ	0x02
+#define AMP_DISCOVER_RSP	0x03
+#define AMP_CHANGE_NOTIFY	0x04
+#define AMP_CHANGE_RSP		0x05
+#define AMP_INFO_REQ		0x06
+#define AMP_INFO_RSP		0x07
+#define AMP_ASSOC_REQ		0x08
+#define AMP_ASSOC_RSP		0x09
+#define AMP_LINK_REQ		0x0a
+#define AMP_LINK_RSP		0x0b
+#define AMP_DISCONN_REQ		0x0c
+#define AMP_DISCONN_RSP		0x0d
+
+typedef struct {
+	uint8_t		code;
+	uint8_t		ident;
+	uint16_t	len;
+} __attribute__ ((packed)) amp_mgr_hdr;
+#define AMP_MGR_HDR_SIZE 4
+
+/* AMP ASSOC structure */
+typedef struct {
+	uint8_t		type_id;
+	uint16_t	len;
+	uint8_t		data[0];
+} __attribute__ ((packed)) amp_assoc_tlv;
+
+typedef struct {
+	uint16_t	reason;
+} __attribute__ ((packed)) amp_cmd_rej_parms;
+
+typedef struct {
+	uint16_t	mtu;
+	uint16_t	mask;
+} __attribute__ ((packed)) amp_discover_req_parms;
+
+typedef struct {
+	uint16_t	mtu;
+	uint16_t	mask;
+	uint8_t		controller_list[0];
+} __attribute__ ((packed)) amp_discover_rsp_parms;
+
+typedef struct {
+	uint8_t		id;
+} __attribute__ ((packed)) amp_info_req_parms;
+
+typedef struct {
+	uint8_t		id;
+	uint8_t		status;
+	uint32_t	total_bandwidth;
+	uint32_t	max_bandwidth;
+	uint32_t	min_latency;
+	uint16_t	pal_caps;
+	uint16_t	assoc_size;
+} __attribute__ ((packed)) amp_info_rsp_parms;
+
+typedef struct {
+	uint8_t		id;
+	uint8_t		status;
+	amp_assoc_tlv	assoc;
+} __attribute__ ((packed)) amp_assoc_rsp_parms;
+
+typedef struct {
+	uint8_t		local_id;
+	uint8_t		remote_id;
+	amp_assoc_tlv	assoc;
+} __attribute__ ((packed)) amp_link_req_parms;
+
+typedef struct {
+	uint8_t		local_id;
+	uint8_t		remote_id;
+	uint8_t		status;
+} __attribute__ ((packed)) amp_link_rsp_parms;
+
+typedef struct {
+	uint8_t		local_id;
+	uint8_t		remote_id;
+} __attribute__ ((packed)) amp_disconn_req_parms;
+
+#define AMP_COMMAND_NOT_RECOGNIZED 0x0000
+
+/* AMP controller status */
+#define AMP_CT_POWERED_DOWN		0x00
+#define AMP_CT_BLUETOOTH_ONLY		0x01
+#define AMP_CT_NO_CAPACITY		0x02
+#define AMP_CT_LOW_CAPACITY		0x03
+#define AMP_CT_MEDIUM_CAPACITY		0x04
+#define AMP_CT_HIGH_CAPACITY		0x05
+#define AMP_CT_FULL_CAPACITY		0x06
+
+/* AMP response status */
+#define AMP_STATUS_SUCCESS				0x00
+#define AMP_STATUS_INVALID_CTRL_ID			0x01
+#define AMP_STATUS_UNABLE_START_LINK_CREATION		0x02
+#define AMP_STATUS_NO_PHYSICAL_LINK_EXISTS		0x02
+#define AMP_STATUS_COLLISION_OCCURED			0x03
+#define AMP_STATUS_DISCONN_REQ_RECVD			0x04
+#define AMP_STATUS_PHYS_LINK_EXISTS			0x05
+#define AMP_STATUS_SECURITY_VIOLATION			0x06
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __AMP_H */
diff --git a/parser/l2cap.c b/parser/l2cap.c
index 7547e8b..7915788 100644
--- a/parser/l2cap.c
+++ b/parser/l2cap.c
@@ -36,6 +36,7 @@
 #include "parser/sdp.h"
 #include "lib/hci.h"
 #include "lib/l2cap.h"
+#include "lib/amp.h"
 
 typedef struct {
 	uint16_t handle;
@@ -259,6 +260,16 @@ static char *reason2str(uint16_t reason)
 	}
 }
 
+static char *ampreason2str(uint16_t reason)
+{
+	switch (reason) {
+	case AMP_COMMAND_NOT_RECOGNIZED:
+		return "Command not recognized";
+	default:
+		return "Reserved";
+	}
+}
+
 static char *connresult2str(uint16_t result)
 {
 	switch (result) {
@@ -399,6 +410,76 @@ static char *supervisory2str(uint8_t supervisory)
 	}
 }
 
+static char *ampctstatus2str(uint8_t status)
+{
+	switch (status) {
+	case AMP_CT_POWERED_DOWN:
+		return "Powered down";
+	case AMP_CT_BLUETOOTH_ONLY:
+		return "Bluetooth only";
+	case AMP_CT_NO_CAPACITY:
+		return "No capacity";
+	case AMP_CT_LOW_CAPACITY:
+		return "Low capacity";
+	case AMP_CT_MEDIUM_CAPACITY:
+		return "Medium capacity";
+	case AMP_CT_HIGH_CAPACITY:
+		return "High capacity";
+	case AMP_CT_FULL_CAPACITY:
+		return "Full capacity";
+	default:
+		return "Reserved";
+
+	}
+}
+
+static char *ampstatus2str(uint8_t status)
+{
+	switch (status) {
+	case AMP_STATUS_SUCCESS:
+		return "Success";
+	case AMP_STATUS_INVALID_CTRL_ID:
+		return "Invalid Controller ID";
+	default:
+		return "Reserved";
+	}
+}
+
+static char *ampcplstatus2str(uint8_t status)
+{
+	switch (status) {
+	case AMP_STATUS_SUCCESS:
+		return "Success";
+	case AMP_STATUS_INVALID_CTRL_ID:
+		return "Invalid Controller ID";
+	case AMP_STATUS_UNABLE_START_LINK_CREATION:
+		return "Failed - Unable to start link creation";
+	case AMP_STATUS_COLLISION_OCCURED:
+		return "Failed - Collision occured";
+	case AMP_STATUS_DISCONN_REQ_RECVD:
+		return "Failed - Disconnect physical link received";
+	case AMP_STATUS_PHYS_LINK_EXISTS:
+		return "Failed - Physical link already exists";
+	case AMP_STATUS_SECURITY_VIOLATION:
+		return "Failed - Security violation";
+	default:
+		return "Reserved";
+	}
+}
+
+static char *ampdplstatus2str(uint8_t status)
+{
+	switch (status) {
+	case AMP_STATUS_SUCCESS:
+		return "Success";
+	case AMP_STATUS_INVALID_CTRL_ID:
+		return "Invalid Controller ID";
+	case AMP_STATUS_NO_PHYSICAL_LINK_EXISTS:
+		return "Failed - No Physical Link exists";
+	default:
+		return "Reserved";
+	}
+}
 
 static inline void command_rej(int level, struct frame *frm)
 {
@@ -923,6 +1004,240 @@ static inline void move_cfm_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm
 	printf("Move cfm rsp: icid 0x%4.4x\n", icid);
 }
 
+static inline void amp_command_rej(int level, struct frame *frm)
+{
+	amp_cmd_rej_parms *h = frm->ptr;
+	uint16_t reason = btohs(h->reason);
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Command Reject: reason (%d)- ", reason);
+	p_indent(level + 1, frm);
+	printf("%s\n", ampreason2str(reason));
+}
+
+static inline void amp_discover_req(int level, struct frame *frm, uint16_t len)
+{
+	amp_discover_req_parms *h = frm->ptr;
+	uint16_t mtu = btohs(h->mtu);
+	uint8_t	 *octet = (uint8_t *)&(h->mask);
+	uint16_t mask;
+	uint8_t  extension;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Discover req: mtu/mps %d ", mtu);
+	len -= 2;
+
+	printf("mask:");
+
+	do {
+		len -= 2;
+		mask = btohs(*(uint16_t *)(&octet[0]));
+		printf(" 0x%4.4x", mask);
+
+		extension = octet[1] & 0x80;
+		octet += 2;
+	} while ((extension != 0) && (len >= 2));
+
+	printf("\n");
+}
+
+static inline void controller_list_dump (int level, uint8_t *octet, uint16_t len)
+{
+	if (p_filter(FILT_A2MP))
+		return;
+
+	p_indent(level, 0);
+	printf("Controller list:\n");
+
+	while (len >= 3) {
+		p_indent(level + 1, 0);
+		printf("id %d, type %d, status 0x%2.2x (%s)\n",
+			   octet[0], octet[1], octet[2], ampctstatus2str(octet[2]));
+		octet += 3;
+		len -= 3;
+	}
+
+}
+
+static inline void amp_discover_rsp(int level, struct frame *frm, uint16_t len)
+{
+	amp_discover_rsp_parms *h = frm->ptr;
+	uint16_t mtu = btohs(h->mtu);
+	uint8_t	 *octet = (uint8_t *)&(h->mask);
+	uint16_t mask;
+	uint8_t  extension;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Discover rsp: mtu/mps %d ", mtu);
+	len -= 2;
+
+	printf("mask:");
+
+	do {
+		len -= 2;
+		mask = btohs(*(uint16_t *)(&octet[0]));
+		printf(" 0x%4.4x", mask);
+
+		extension = octet[1] & 0x80;
+		octet += 2;
+	} while ((extension != 0) && (len >= 2));
+
+	printf("\n");
+
+	if (len >= 3) {
+		controller_list_dump (level + 1, octet, len);
+	}
+}
+
+static inline void amp_change_notify(int level, struct frame *frm, uint16_t len)
+{
+	uint8_t *octet = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Change Notify\n");
+
+	if (len >= 3) {
+		controller_list_dump (level + 1, octet, len);
+	}
+}
+
+static inline void amp_change_rsp(int level, struct frame *frm)
+{
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Change Response\n");
+}
+
+static inline void amp_info_req(int level, struct frame *frm)
+{
+	amp_info_req_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Get Info req: id %d\n", h->id);
+}
+
+static inline void amp_info_rsp(int level, struct frame *frm)
+{
+	amp_info_rsp_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Get Info rsp: id %d status (%d) %s\n",
+		   h->id, h->status, ampstatus2str(h->status));
+
+	p_indent(level + 1, frm);
+	printf("total bandwidth %d\n", btohl(h->total_bandwidth));
+	p_indent(level + 1, frm);
+	printf("max guaranteed bandwidth %d\n", btohl(h->max_bandwidth));
+	p_indent(level + 1, frm);
+	printf("min latency %d\n", btohl(h->min_latency));
+	p_indent(level + 1, frm);
+	printf("pal capabilities 0x%4.4x\n", btohs(h->pal_caps));
+	p_indent(level + 1, frm);
+	printf("assoc size %d\n", btohs(h->assoc_size));
+}
+
+static inline void amp_assoc_req(int level, struct frame *frm)
+{
+	amp_info_req_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Get AMP Assoc req: id %d\n", h->id);
+}
+
+static inline void amp_assoc_dump(int level, uint8_t *assoc, uint16_t len)
+{
+	int i;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	p_indent(level, 0);
+	printf("assoc data:");
+	for (i = 0; i < len; i++) {
+		if (!(i%16)) printf("\n");
+		if (!(i%16)) p_indent(level+1, 0);
+		printf("%2.2x ",*assoc++);
+	}
+	printf("\n");
+
+}
+
+static inline void amp_assoc_rsp(int level, struct frame *frm, uint16_t len)
+{
+	amp_assoc_rsp_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Get AMP Assoc rsp: id %d status (%d) %s \n",
+		   h->id, h->status, ampstatus2str(h->status));
+	amp_assoc_dump(level + 1, (uint8_t *) &h->assoc, len - 2);
+}
+
+static inline void amp_link_req(int level, struct frame *frm, uint16_t len)
+{
+	amp_link_req_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Create Physical Link req: local id %d remote id %d\n",
+		   h->local_id, h->remote_id);
+	amp_assoc_dump(level + 1, (uint8_t *) &h->assoc, len - 2);
+}
+
+static inline void amp_link_rsp(int level, struct frame *frm)
+{
+	amp_link_rsp_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Create Physical Link rsp: local id %d remote id %d status %d\n",
+		   h->local_id, h->remote_id, h->status);
+	p_indent(level+1, 0);
+	printf("%s\n", ampcplstatus2str(h->status));
+}
+
+static inline void amp_disconn_req(int level, struct frame *frm)
+{
+	amp_disconn_req_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Disconnect Physical Link req: local id %d remote id %d\n",
+		   h->local_id, h->remote_id);
+}
+
+static inline void amp_disconn_rsp(int level, struct frame *frm)
+{
+	amp_link_rsp_parms *h = frm->ptr;
+
+	if (p_filter(FILT_A2MP))
+		return;
+
+	printf("Disconnect Physical Link rsp: local id %d remote id %d status %d\n",
+		   h->local_id, h->remote_id, h->status);
+	p_indent(level+1, 0);
+	printf("%s\n", ampdplstatus2str(h->status));
+}
+
 static void l2cap_parse(int level, struct frame *frm)
 {
 	l2cap_hdr *hdr = (void *)frm->ptr;
@@ -1043,6 +1358,76 @@ static void l2cap_parse(int level, struct frame *frm)
 		p_indent(level, frm);
 		printf("L2CAP(c): len %d psm %d\n", dlen, psm);
 		raw_dump(level, frm);
+	} else if ((cid == 0x3) && (frm->len > 4)) {
+
+		/* Adjust for extra ERTM control bytes */
+		frm->ptr += 2;
+		frm->len -= 2;
+
+		while (frm->len >= AMP_MGR_HDR_SIZE) {
+			amp_mgr_hdr *hdr = frm->ptr;
+
+			frm->ptr += AMP_MGR_HDR_SIZE;
+			frm->len -= AMP_MGR_HDR_SIZE;
+
+			if (!p_filter(FILT_A2MP)) {
+				p_indent(level, frm);
+				printf("A2MP: ");
+			}
+			switch (hdr->code) {
+			case AMP_COMMAND_REJ:
+				amp_command_rej(level, frm);
+				break;
+			case AMP_DISCOVER_REQ:
+				amp_discover_req(level, frm, hdr->len);
+				break;
+			case AMP_DISCOVER_RSP:
+				amp_discover_rsp(level, frm, hdr->len);
+				break;
+			case AMP_CHANGE_NOTIFY:
+				amp_change_notify(level, frm, hdr->len);
+				break;
+			case AMP_CHANGE_RSP:
+				amp_change_rsp(level, frm);
+				break;
+			case AMP_INFO_REQ:
+				amp_info_req(level, frm);
+				break;
+			case AMP_INFO_RSP:
+				amp_info_rsp(level, frm);
+				break;
+			case AMP_ASSOC_REQ:
+				amp_assoc_req(level, frm);
+				break;
+			case AMP_ASSOC_RSP:
+				amp_assoc_rsp(level, frm, hdr->len);
+				break;
+			case AMP_LINK_REQ:
+				amp_link_req(level, frm, hdr->len);
+				break;
+			case AMP_LINK_RSP:
+				amp_link_rsp(level, frm);
+				break;
+			case AMP_DISCONN_REQ:
+				amp_disconn_req(level, frm);
+				break;
+			case AMP_DISCONN_RSP:
+				amp_disconn_rsp(level, frm);
+				break;
+			default:
+				if (p_filter(FILT_A2MP))
+					break;
+				printf("code 0x%2.2x ident %d len %d\n",
+					   hdr->code, hdr->ident, btohs(hdr->len));
+				raw_dump(level, frm);
+			}
+
+			if (frm->len > btohs(hdr->len)) {
+				frm->len -= btohs(hdr->len);
+				frm->ptr += btohs(hdr->len);
+			} else
+				frm->len = 0;
+		}
 	} else if (cid == 0x04) {
 		if (!p_filter(FILT_ATT))
 			att_dump(level, frm);
diff --git a/parser/parser.h b/parser/parser.h
index e975808..22d18c3 100644
--- a/parser/parser.h
+++ b/parser/parser.h
@@ -80,6 +80,7 @@ struct frame {
 #define FILT_AVCTP	0x0800
 #define FILT_ATT 	0x1000
 #define FILT_SMP	0x2000
+#define FILT_A2MP	0x4000
 
 #define FILT_OBEX	0x00010000
 #define FILT_CAPI	0x00020000
diff --git a/src/hcidump.c b/src/hcidump.c
index 0c13360..2513c7c 100644
--- a/src/hcidump.c
+++ b/src/hcidump.c
@@ -802,6 +802,7 @@ static struct {
 	{ "hci",	FILT_HCI	},
 	{ "sco",	FILT_SCO	},
 	{ "l2cap",	FILT_L2CAP	},
+	{ "a2mp",	FILT_A2MP	},
 	{ "rfcomm",	FILT_RFCOMM	},
 	{ "sdp",	FILT_SDP	},
 	{ "bnep",	FILT_BNEP	},
-- 
1.7.7

--
Peter Krystad
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] Add parsing of L2CAP Fixed Channel list
  2011-10-21 23:29 [PATCH 0/4] Add parsing of BT 3.0+HS signalling Peter Krystad
  2011-10-21 23:29 ` [PATCH 1/4] Add parsing of L2CAP Create/Move Channel signals Peter Krystad
  2011-10-21 23:30 ` [PATCH 2/4] Add parsing of A2MP signals Peter Krystad
@ 2011-10-21 23:30 ` Peter Krystad
  2011-10-24  7:51   ` Andrei Emeltchenko
  2011-10-21 23:30 ` [PATCH 4/4] Minor cleanup of indentation in output Peter Krystad
  3 siblings, 1 reply; 10+ messages in thread
From: Peter Krystad @ 2011-10-21 23:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andrei.emeltchenko, Peter Krystad

Add DUMP_VERBOSE display of L2CAP Fixed Channel list.
Example output:

2011-10-21 12:01:50.423246 > ACL data: handle 39 flags 0x02 dlen 20
    L2CAP(s): Info rsp: type 3 result 0
      Fixed channel list
        L2CAP
        CONNLESS
        A2MP
---
 parser/l2cap.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/parser/l2cap.c b/parser/l2cap.c
index 7915788..ce78d05 100644
--- a/parser/l2cap.c
+++ b/parser/l2cap.c
@@ -811,6 +811,7 @@ static void info_opt(int level, int type, void *ptr, int len)
 {
 	uint32_t mask;
 	int i;
+	uint8_t list;
 
 	p_indent(level, 0);
 
@@ -830,6 +831,21 @@ static void info_opt(int level, int type, void *ptr, int len)
 		break;
 	case 0x0003:
 		printf("Fixed channel list\n");
+		list = get_val(ptr, 1);
+		if (parser.flags & DUMP_VERBOSE) {
+			if (list & L2CAP_FC_L2CAP) {
+				p_indent(level + 1, 0);
+				printf("L2CAP\n");
+			}
+			if (list & L2CAP_FC_CONNLESS) {
+				p_indent(level + 1, 0);
+				printf("CONNLESS\n");
+			}
+			if (list & L2CAP_FC_A2MP) {
+				p_indent(level + 1, 0);
+				printf("A2MP\n");
+			}
+		}
 		break;
 	default:
 		printf("Unknown (len %d)\n", len);
-- 
1.7.7

--
Peter Krystad
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] Minor cleanup of indentation in output
  2011-10-21 23:29 [PATCH 0/4] Add parsing of BT 3.0+HS signalling Peter Krystad
                   ` (2 preceding siblings ...)
  2011-10-21 23:30 ` [PATCH 3/4] Add parsing of L2CAP Fixed Channel list Peter Krystad
@ 2011-10-21 23:30 ` Peter Krystad
  3 siblings, 0 replies; 10+ messages in thread
From: Peter Krystad @ 2011-10-21 23:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andrei.emeltchenko, Peter Krystad

Minor indentation cleanup and fix display of physical link key
---
 parser/hci.c |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/parser/hci.c b/parser/hci.c
index a0e3034..e459e9e 100644
--- a/parser/hci.c
+++ b/parser/hci.c
@@ -1124,12 +1124,11 @@ static inline void create_physical_link_dump(int level, struct frame *frm)
 	int i;
 
 	p_indent(level, frm);
-
 	printf("handle %d key length %d key type %d\n",
 		cp->handle, cp->key_length, cp->key_type);
+	p_indent(level, frm);
 	printf("key ");
-
-	for (i = 0; i < cp->key_length && cp->key_length < 32; i++)
+	for (i = 0; i < cp->key_length && cp->key_length <= 32; i++)
 		printf("%2.2x", cp->key[i]);
 	printf("\n");
 }
@@ -1140,12 +1139,16 @@ static inline void create_logical_link_dump(int level, struct frame *frm)
 	int i;
 
 	p_indent(level, frm);
-
 	printf("handle %d\n", cp->handle);
+
+	p_indent(level, frm);
 	printf("tx_flow ");
 	for (i = 0; i < 16; i++)
 		printf("%2.2x", cp->tx_flow[i]);
-	printf("\nrx_flow ");
+	printf("\n");
+
+	p_indent(level, frm);
+	printf("rx_flow ");
 	for (i = 0; i < 16; i++)
 		printf("%2.2x", cp->rx_flow[i]);
 	printf("\n");
@@ -2605,6 +2608,8 @@ static inline void read_local_amp_assoc_dump(int level, struct frame *frm)
 		p_indent(level, frm);
 		printf("Error: %s\n", status2str(rp->status));
 	} else {
+		p_indent(level, frm);
+		printf("assoc data");
 		for (i = 0; i < len; i++) {
 			if (!(i % 16)) {
 				printf("\n");
-- 
1.7.7

--
Peter Krystad
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/4] Add parsing of L2CAP Create/Move Channel signals
  2011-10-21 23:29 ` [PATCH 1/4] Add parsing of L2CAP Create/Move Channel signals Peter Krystad
@ 2011-10-22  7:21   ` Marcel Holtmann
  0 siblings, 0 replies; 10+ messages in thread
From: Marcel Holtmann @ 2011-10-22  7:21 UTC (permalink / raw)
  To: Peter Krystad; +Cc: linux-bluetooth, andrei.emeltchenko

Hi Peter,

> Add parsing of L2CAP Create/Move Channel signalling.
> Example output:
> 
> 2011-10-18 16:09:47.810208 > ACL data: handle 39 flags 0x02 dlen 13
>     L2CAP(s): Create req: psm 4097 scid 0x4201 id 17
> 2011-10-18 16:09:47.810269 < ACL data: handle 39 flags 0x00 dlen 16
>     L2CAP(s): Create rsp: dcid 0x0040 scid 0x4201 result 1 status 0
> 2011-10-18 16:09:47.898308 < ACL data: handle 39 flags 0x00 dlen 16
>     L2CAP(s): Create rsp: dcid 0x0040 scid 0x4201 result 0 status 0
> 
> ....
> 
> 2011-10-18 14:25:24.646869 > ACL data: handle 39 flags 0x02 dlen 11
>     L2CAP(s): Move req: icid 0x4000 id 17
> 2011-10-18 14:25:24.646987 < ACL data: handle 39 flags 0x00 dlen 12
>     L2CAP(s): Move rsp: icid 0x4000 result 1
> 2011-10-18 14:25:24.846873 < ACL data: handle 39 flags 0x00 dlen 12
>     L2CAP(s): Move rsp: icid 0x4000 result 0
> 2011-10-18 14:25:25.041844 > ACL data: handle 39 flags 0x02 dlen 12
>     L2CAP(s): Move cfm: icid 0x4000 result 0
> 2011-10-18 14:25:25.041945 < ACL data: handle 39 flags 0x00 dlen 10
>     L2CAP(s): Move cfm rsp: icid 0x4000
> ---
>  lib/l2cap.h    |   50 +++++++++++++++++++++++++++++
>  parser/l2cap.c |   97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 147 insertions(+), 0 deletions(-)

same requirement as with Andrei's patches before. First get them
accepted into bluez.git and then we port them over here.

Regards

Marcel



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] Add parsing of A2MP signals
  2011-10-21 23:30 ` [PATCH 2/4] Add parsing of A2MP signals Peter Krystad
@ 2011-10-24  7:34   ` Andrei Emeltchenko
  2011-10-26 13:33   ` Andrei Emeltchenko
  1 sibling, 0 replies; 10+ messages in thread
From: Andrei Emeltchenko @ 2011-10-24  7:34 UTC (permalink / raw)
  To: Peter Krystad; +Cc: linux-bluetooth

Hi Peter,

On Fri, Oct 21, 2011 at 04:30:00PM -0700, Peter Krystad wrote:
> Add parsing of A2MP signalling.
> Example output:
> 
> 2011-10-18 16:09:44.493202 > ACL data: handle 39 flags 0x02 dlen 16
>     A2MP: Discover req: mtu/mps 670 mask: 0x0000
> 2011-10-18 16:09:44.493404 < ACL data: handle 39 flags 0x00 dlen 22
>     A2MP: Discover rsp: mtu/mps 670 mask: 0x0000
>       Controller list:
>         id 0, type 0, status 0x01 (Bluetooth only)
>         id 17, type 254, status 0x06 (Full capacity)
> 2011-10-18 16:09:44.697203 > ACL data: handle 39 flags 0x02 dlen 13
>     A2MP: Get Info req: id 17
> 2011-10-18 16:09:44.697312 < ACL data: handle 39 flags 0x00 dlen 30
>     A2MP: Get Info rsp: id 17 status (0) Success
>       total bandwidth 500000
>       max guaranteed bandwidth 0
>       min latency 100000
>       pal capabilities 0x0000
>       assoc size 8
> 2011-10-18 16:09:44.893203 > ACL data: handle 39 flags 0x02 dlen 13
>     A2MP: Get AMP Assoc req: id 17
> 2011-10-18 16:09:44.893618 < ACL data: handle 39 flags 0x00 dlen 22
>     A2MP: Get AMP Assoc rsp: id 17 status (0) Success
>       assoc data:
>         08 01 b1 01 0a 04 6c 42
> 2011-10-18 16:09:45.598201 > ACL data: handle 39 flags 0x02 dlen 22
>     A2MP: Create Physical Link req: local id 1 remote id 17
>       assoc data:
>         08 01 b1 01 0a 04 6d 38
> 2011-10-18 16:09:45.598643 < ACL data: handle 39 flags 0x00 dlen 15
>     A2MP: Create Physical Link rsp: local id 17 remote id 1 status 0
>       Success
> ---
>  lib/amp.h       |  133 +++++++++++++++++++
>  parser/l2cap.c  |  385 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  parser/parser.h |    1 +
>  src/hcidump.c   |    1 +
>  4 files changed, 520 insertions(+), 0 deletions(-)
>  create mode 100644 lib/amp.h
> 
> diff --git a/lib/amp.h b/lib/amp.h

Minor comments. Would it be better to name it a2mp.h and functions below a2mp_*?

Otherwise as Marcel mentioned header patches shall be applied first to
bluez.

Best regards 
Andrei Emeltchenko 

> new file mode 100644
> index 0000000..0c6300a
> --- /dev/null
> +++ b/lib/amp.h
> @@ -0,0 +1,133 @@
> +/*
> + *
> + *	BlueZ - Bluetooth protocol stack for Linux
> + *
> + *	Copyright (C) 2010-2011 Code Aurora Forum.  All rights reserved.
> + *
> + *	This program is free software; you can redistribute it and/or modify
> + *	it under the terms of the GNU General Public License version 2 and
> + *	only version 2 as published by the Free Software Foundation.
> + *
> + *	This program 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 General Public License for more details.
> + *
> + */
> +
> +#ifndef __AMP_H
> +#define __AMP_H
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#define AMP_MGR_CID 0x03
> +
> +/* AMP manager codes */
> +#define AMP_COMMAND_REJ		0x01
> +#define AMP_DISCOVER_REQ	0x02
> +#define AMP_DISCOVER_RSP	0x03
> +#define AMP_CHANGE_NOTIFY	0x04
> +#define AMP_CHANGE_RSP		0x05
> +#define AMP_INFO_REQ		0x06
> +#define AMP_INFO_RSP		0x07
> +#define AMP_ASSOC_REQ		0x08
> +#define AMP_ASSOC_RSP		0x09
> +#define AMP_LINK_REQ		0x0a
> +#define AMP_LINK_RSP		0x0b
> +#define AMP_DISCONN_REQ		0x0c
> +#define AMP_DISCONN_RSP		0x0d
> +
> +typedef struct {
> +	uint8_t		code;
> +	uint8_t		ident;
> +	uint16_t	len;
> +} __attribute__ ((packed)) amp_mgr_hdr;
> +#define AMP_MGR_HDR_SIZE 4
> +
> +/* AMP ASSOC structure */
> +typedef struct {
> +	uint8_t		type_id;
> +	uint16_t	len;
> +	uint8_t		data[0];
> +} __attribute__ ((packed)) amp_assoc_tlv;
> +
> +typedef struct {
> +	uint16_t	reason;
> +} __attribute__ ((packed)) amp_cmd_rej_parms;
> +
> +typedef struct {
> +	uint16_t	mtu;
> +	uint16_t	mask;
> +} __attribute__ ((packed)) amp_discover_req_parms;
> +
> +typedef struct {
> +	uint16_t	mtu;
> +	uint16_t	mask;
> +	uint8_t		controller_list[0];
> +} __attribute__ ((packed)) amp_discover_rsp_parms;
> +
> +typedef struct {
> +	uint8_t		id;
> +} __attribute__ ((packed)) amp_info_req_parms;
> +
> +typedef struct {
> +	uint8_t		id;
> +	uint8_t		status;
> +	uint32_t	total_bandwidth;
> +	uint32_t	max_bandwidth;
> +	uint32_t	min_latency;
> +	uint16_t	pal_caps;
> +	uint16_t	assoc_size;
> +} __attribute__ ((packed)) amp_info_rsp_parms;
> +
> +typedef struct {
> +	uint8_t		id;
> +	uint8_t		status;
> +	amp_assoc_tlv	assoc;
> +} __attribute__ ((packed)) amp_assoc_rsp_parms;
> +
> +typedef struct {
> +	uint8_t		local_id;
> +	uint8_t		remote_id;
> +	amp_assoc_tlv	assoc;
> +} __attribute__ ((packed)) amp_link_req_parms;
> +
> +typedef struct {
> +	uint8_t		local_id;
> +	uint8_t		remote_id;
> +	uint8_t		status;
> +} __attribute__ ((packed)) amp_link_rsp_parms;
> +
> +typedef struct {
> +	uint8_t		local_id;
> +	uint8_t		remote_id;
> +} __attribute__ ((packed)) amp_disconn_req_parms;
> +
> +#define AMP_COMMAND_NOT_RECOGNIZED 0x0000
> +
> +/* AMP controller status */
> +#define AMP_CT_POWERED_DOWN		0x00
> +#define AMP_CT_BLUETOOTH_ONLY		0x01
> +#define AMP_CT_NO_CAPACITY		0x02
> +#define AMP_CT_LOW_CAPACITY		0x03
> +#define AMP_CT_MEDIUM_CAPACITY		0x04
> +#define AMP_CT_HIGH_CAPACITY		0x05
> +#define AMP_CT_FULL_CAPACITY		0x06
> +
> +/* AMP response status */
> +#define AMP_STATUS_SUCCESS				0x00
> +#define AMP_STATUS_INVALID_CTRL_ID			0x01
> +#define AMP_STATUS_UNABLE_START_LINK_CREATION		0x02
> +#define AMP_STATUS_NO_PHYSICAL_LINK_EXISTS		0x02
> +#define AMP_STATUS_COLLISION_OCCURED			0x03
> +#define AMP_STATUS_DISCONN_REQ_RECVD			0x04
> +#define AMP_STATUS_PHYS_LINK_EXISTS			0x05
> +#define AMP_STATUS_SECURITY_VIOLATION			0x06
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __AMP_H */
> diff --git a/parser/l2cap.c b/parser/l2cap.c
> index 7547e8b..7915788 100644
> --- a/parser/l2cap.c
> +++ b/parser/l2cap.c
> @@ -36,6 +36,7 @@
>  #include "parser/sdp.h"
>  #include "lib/hci.h"
>  #include "lib/l2cap.h"
> +#include "lib/amp.h"
>  
>  typedef struct {
>  	uint16_t handle;
> @@ -259,6 +260,16 @@ static char *reason2str(uint16_t reason)
>  	}
>  }
>  
> +static char *ampreason2str(uint16_t reason)
> +{
> +	switch (reason) {
> +	case AMP_COMMAND_NOT_RECOGNIZED:
> +		return "Command not recognized";
> +	default:
> +		return "Reserved";
> +	}
> +}
> +
>  static char *connresult2str(uint16_t result)
>  {
>  	switch (result) {
> @@ -399,6 +410,76 @@ static char *supervisory2str(uint8_t supervisory)
>  	}
>  }
>  
> +static char *ampctstatus2str(uint8_t status)
> +{
> +	switch (status) {
> +	case AMP_CT_POWERED_DOWN:
> +		return "Powered down";
> +	case AMP_CT_BLUETOOTH_ONLY:
> +		return "Bluetooth only";
> +	case AMP_CT_NO_CAPACITY:
> +		return "No capacity";
> +	case AMP_CT_LOW_CAPACITY:
> +		return "Low capacity";
> +	case AMP_CT_MEDIUM_CAPACITY:
> +		return "Medium capacity";
> +	case AMP_CT_HIGH_CAPACITY:
> +		return "High capacity";
> +	case AMP_CT_FULL_CAPACITY:
> +		return "Full capacity";
> +	default:
> +		return "Reserved";
> +
> +	}
> +}
> +
> +static char *ampstatus2str(uint8_t status)
> +{
> +	switch (status) {
> +	case AMP_STATUS_SUCCESS:
> +		return "Success";
> +	case AMP_STATUS_INVALID_CTRL_ID:
> +		return "Invalid Controller ID";
> +	default:
> +		return "Reserved";
> +	}
> +}
> +
> +static char *ampcplstatus2str(uint8_t status)
> +{
> +	switch (status) {
> +	case AMP_STATUS_SUCCESS:
> +		return "Success";
> +	case AMP_STATUS_INVALID_CTRL_ID:
> +		return "Invalid Controller ID";
> +	case AMP_STATUS_UNABLE_START_LINK_CREATION:
> +		return "Failed - Unable to start link creation";
> +	case AMP_STATUS_COLLISION_OCCURED:
> +		return "Failed - Collision occured";
> +	case AMP_STATUS_DISCONN_REQ_RECVD:
> +		return "Failed - Disconnect physical link received";
> +	case AMP_STATUS_PHYS_LINK_EXISTS:
> +		return "Failed - Physical link already exists";
> +	case AMP_STATUS_SECURITY_VIOLATION:
> +		return "Failed - Security violation";
> +	default:
> +		return "Reserved";
> +	}
> +}
> +
> +static char *ampdplstatus2str(uint8_t status)
> +{
> +	switch (status) {
> +	case AMP_STATUS_SUCCESS:
> +		return "Success";
> +	case AMP_STATUS_INVALID_CTRL_ID:
> +		return "Invalid Controller ID";
> +	case AMP_STATUS_NO_PHYSICAL_LINK_EXISTS:
> +		return "Failed - No Physical Link exists";
> +	default:
> +		return "Reserved";
> +	}
> +}
>  
>  static inline void command_rej(int level, struct frame *frm)
>  {
> @@ -923,6 +1004,240 @@ static inline void move_cfm_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm
>  	printf("Move cfm rsp: icid 0x%4.4x\n", icid);
>  }
>  
> +static inline void amp_command_rej(int level, struct frame *frm)
> +{
> +	amp_cmd_rej_parms *h = frm->ptr;
> +	uint16_t reason = btohs(h->reason);
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Command Reject: reason (%d)- ", reason);
> +	p_indent(level + 1, frm);
> +	printf("%s\n", ampreason2str(reason));
> +}
> +
> +static inline void amp_discover_req(int level, struct frame *frm, uint16_t len)
> +{
> +	amp_discover_req_parms *h = frm->ptr;
> +	uint16_t mtu = btohs(h->mtu);
> +	uint8_t	 *octet = (uint8_t *)&(h->mask);
> +	uint16_t mask;
> +	uint8_t  extension;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Discover req: mtu/mps %d ", mtu);
> +	len -= 2;
> +
> +	printf("mask:");
> +
> +	do {
> +		len -= 2;
> +		mask = btohs(*(uint16_t *)(&octet[0]));
> +		printf(" 0x%4.4x", mask);
> +
> +		extension = octet[1] & 0x80;
> +		octet += 2;
> +	} while ((extension != 0) && (len >= 2));
> +
> +	printf("\n");
> +}
> +
> +static inline void controller_list_dump (int level, uint8_t *octet, uint16_t len)
> +{
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	p_indent(level, 0);
> +	printf("Controller list:\n");
> +
> +	while (len >= 3) {
> +		p_indent(level + 1, 0);
> +		printf("id %d, type %d, status 0x%2.2x (%s)\n",
> +			   octet[0], octet[1], octet[2], ampctstatus2str(octet[2]));
> +		octet += 3;
> +		len -= 3;
> +	}
> +
> +}
> +
> +static inline void amp_discover_rsp(int level, struct frame *frm, uint16_t len)
> +{
> +	amp_discover_rsp_parms *h = frm->ptr;
> +	uint16_t mtu = btohs(h->mtu);
> +	uint8_t	 *octet = (uint8_t *)&(h->mask);
> +	uint16_t mask;
> +	uint8_t  extension;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Discover rsp: mtu/mps %d ", mtu);
> +	len -= 2;
> +
> +	printf("mask:");
> +
> +	do {
> +		len -= 2;
> +		mask = btohs(*(uint16_t *)(&octet[0]));
> +		printf(" 0x%4.4x", mask);
> +
> +		extension = octet[1] & 0x80;
> +		octet += 2;
> +	} while ((extension != 0) && (len >= 2));
> +
> +	printf("\n");
> +
> +	if (len >= 3) {
> +		controller_list_dump (level + 1, octet, len);
> +	}
> +}
> +
> +static inline void amp_change_notify(int level, struct frame *frm, uint16_t len)
> +{
> +	uint8_t *octet = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Change Notify\n");
> +
> +	if (len >= 3) {
> +		controller_list_dump (level + 1, octet, len);
> +	}
> +}
> +
> +static inline void amp_change_rsp(int level, struct frame *frm)
> +{
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Change Response\n");
> +}
> +
> +static inline void amp_info_req(int level, struct frame *frm)
> +{
> +	amp_info_req_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Get Info req: id %d\n", h->id);
> +}
> +
> +static inline void amp_info_rsp(int level, struct frame *frm)
> +{
> +	amp_info_rsp_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Get Info rsp: id %d status (%d) %s\n",
> +		   h->id, h->status, ampstatus2str(h->status));
> +
> +	p_indent(level + 1, frm);
> +	printf("total bandwidth %d\n", btohl(h->total_bandwidth));
> +	p_indent(level + 1, frm);
> +	printf("max guaranteed bandwidth %d\n", btohl(h->max_bandwidth));
> +	p_indent(level + 1, frm);
> +	printf("min latency %d\n", btohl(h->min_latency));
> +	p_indent(level + 1, frm);
> +	printf("pal capabilities 0x%4.4x\n", btohs(h->pal_caps));
> +	p_indent(level + 1, frm);
> +	printf("assoc size %d\n", btohs(h->assoc_size));
> +}
> +
> +static inline void amp_assoc_req(int level, struct frame *frm)
> +{
> +	amp_info_req_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Get AMP Assoc req: id %d\n", h->id);
> +}
> +
> +static inline void amp_assoc_dump(int level, uint8_t *assoc, uint16_t len)
> +{
> +	int i;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	p_indent(level, 0);
> +	printf("assoc data:");
> +	for (i = 0; i < len; i++) {
> +		if (!(i%16)) printf("\n");
> +		if (!(i%16)) p_indent(level+1, 0);
> +		printf("%2.2x ",*assoc++);
> +	}
> +	printf("\n");
> +
> +}
> +
> +static inline void amp_assoc_rsp(int level, struct frame *frm, uint16_t len)
> +{
> +	amp_assoc_rsp_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Get AMP Assoc rsp: id %d status (%d) %s \n",
> +		   h->id, h->status, ampstatus2str(h->status));
> +	amp_assoc_dump(level + 1, (uint8_t *) &h->assoc, len - 2);
> +}
> +
> +static inline void amp_link_req(int level, struct frame *frm, uint16_t len)
> +{
> +	amp_link_req_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Create Physical Link req: local id %d remote id %d\n",
> +		   h->local_id, h->remote_id);
> +	amp_assoc_dump(level + 1, (uint8_t *) &h->assoc, len - 2);
> +}
> +
> +static inline void amp_link_rsp(int level, struct frame *frm)
> +{
> +	amp_link_rsp_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Create Physical Link rsp: local id %d remote id %d status %d\n",
> +		   h->local_id, h->remote_id, h->status);
> +	p_indent(level+1, 0);
> +	printf("%s\n", ampcplstatus2str(h->status));
> +}
> +
> +static inline void amp_disconn_req(int level, struct frame *frm)
> +{
> +	amp_disconn_req_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Disconnect Physical Link req: local id %d remote id %d\n",
> +		   h->local_id, h->remote_id);
> +}
> +
> +static inline void amp_disconn_rsp(int level, struct frame *frm)
> +{
> +	amp_link_rsp_parms *h = frm->ptr;
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Disconnect Physical Link rsp: local id %d remote id %d status %d\n",
> +		   h->local_id, h->remote_id, h->status);
> +	p_indent(level+1, 0);
> +	printf("%s\n", ampdplstatus2str(h->status));
> +}
> +
>  static void l2cap_parse(int level, struct frame *frm)
>  {
>  	l2cap_hdr *hdr = (void *)frm->ptr;
> @@ -1043,6 +1358,76 @@ static void l2cap_parse(int level, struct frame *frm)
>  		p_indent(level, frm);
>  		printf("L2CAP(c): len %d psm %d\n", dlen, psm);
>  		raw_dump(level, frm);
> +	} else if ((cid == 0x3) && (frm->len > 4)) {
> +
> +		/* Adjust for extra ERTM control bytes */
> +		frm->ptr += 2;
> +		frm->len -= 2;
> +
> +		while (frm->len >= AMP_MGR_HDR_SIZE) {
> +			amp_mgr_hdr *hdr = frm->ptr;
> +
> +			frm->ptr += AMP_MGR_HDR_SIZE;
> +			frm->len -= AMP_MGR_HDR_SIZE;
> +
> +			if (!p_filter(FILT_A2MP)) {
> +				p_indent(level, frm);
> +				printf("A2MP: ");
> +			}
> +			switch (hdr->code) {
> +			case AMP_COMMAND_REJ:
> +				amp_command_rej(level, frm);
> +				break;
> +			case AMP_DISCOVER_REQ:
> +				amp_discover_req(level, frm, hdr->len);
> +				break;
> +			case AMP_DISCOVER_RSP:
> +				amp_discover_rsp(level, frm, hdr->len);
> +				break;
> +			case AMP_CHANGE_NOTIFY:
> +				amp_change_notify(level, frm, hdr->len);
> +				break;
> +			case AMP_CHANGE_RSP:
> +				amp_change_rsp(level, frm);
> +				break;
> +			case AMP_INFO_REQ:
> +				amp_info_req(level, frm);
> +				break;
> +			case AMP_INFO_RSP:
> +				amp_info_rsp(level, frm);
> +				break;
> +			case AMP_ASSOC_REQ:
> +				amp_assoc_req(level, frm);
> +				break;
> +			case AMP_ASSOC_RSP:
> +				amp_assoc_rsp(level, frm, hdr->len);
> +				break;
> +			case AMP_LINK_REQ:
> +				amp_link_req(level, frm, hdr->len);
> +				break;
> +			case AMP_LINK_RSP:
> +				amp_link_rsp(level, frm);
> +				break;
> +			case AMP_DISCONN_REQ:
> +				amp_disconn_req(level, frm);
> +				break;
> +			case AMP_DISCONN_RSP:
> +				amp_disconn_rsp(level, frm);
> +				break;
> +			default:
> +				if (p_filter(FILT_A2MP))
> +					break;
> +				printf("code 0x%2.2x ident %d len %d\n",
> +					   hdr->code, hdr->ident, btohs(hdr->len));
> +				raw_dump(level, frm);
> +			}
> +
> +			if (frm->len > btohs(hdr->len)) {
> +				frm->len -= btohs(hdr->len);
> +				frm->ptr += btohs(hdr->len);
> +			} else
> +				frm->len = 0;
> +		}
>  	} else if (cid == 0x04) {
>  		if (!p_filter(FILT_ATT))
>  			att_dump(level, frm);
> diff --git a/parser/parser.h b/parser/parser.h
> index e975808..22d18c3 100644
> --- a/parser/parser.h
> +++ b/parser/parser.h
> @@ -80,6 +80,7 @@ struct frame {
>  #define FILT_AVCTP	0x0800
>  #define FILT_ATT 	0x1000
>  #define FILT_SMP	0x2000
> +#define FILT_A2MP	0x4000
>  
>  #define FILT_OBEX	0x00010000
>  #define FILT_CAPI	0x00020000
> diff --git a/src/hcidump.c b/src/hcidump.c
> index 0c13360..2513c7c 100644
> --- a/src/hcidump.c
> +++ b/src/hcidump.c
> @@ -802,6 +802,7 @@ static struct {
>  	{ "hci",	FILT_HCI	},
>  	{ "sco",	FILT_SCO	},
>  	{ "l2cap",	FILT_L2CAP	},
> +	{ "a2mp",	FILT_A2MP	},
>  	{ "rfcomm",	FILT_RFCOMM	},
>  	{ "sdp",	FILT_SDP	},
>  	{ "bnep",	FILT_BNEP	},
> -- 
> 1.7.7
> 
> --
> Peter Krystad
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
> --
> 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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] Add parsing of L2CAP Fixed Channel list
  2011-10-21 23:30 ` [PATCH 3/4] Add parsing of L2CAP Fixed Channel list Peter Krystad
@ 2011-10-24  7:51   ` Andrei Emeltchenko
  0 siblings, 0 replies; 10+ messages in thread
From: Andrei Emeltchenko @ 2011-10-24  7:51 UTC (permalink / raw)
  To: Peter Krystad; +Cc: linux-bluetooth

Hi Peter,

On Fri, Oct 21, 2011 at 04:30:01PM -0700, Peter Krystad wrote:
> Add DUMP_VERBOSE display of L2CAP Fixed Channel list.
> Example output:
> 
> 2011-10-21 12:01:50.423246 > ACL data: handle 39 flags 0x02 dlen 20
>     L2CAP(s): Info rsp: type 3 result 0
>       Fixed channel list
>         L2CAP
>         CONNLESS
>         A2MP

We can be more specific here since each channel is printed on new line

> ---
>  parser/l2cap.c |   16 ++++++++++++++++
>  1 files changed, 16 insertions(+), 0 deletions(-)
> 
> diff --git a/parser/l2cap.c b/parser/l2cap.c
> index 7915788..ce78d05 100644
> --- a/parser/l2cap.c
> +++ b/parser/l2cap.c
> @@ -811,6 +811,7 @@ static void info_opt(int level, int type, void *ptr, int len)
>  {
>  	uint32_t mask;
>  	int i;
> +	uint8_t list;
>  
>  	p_indent(level, 0);
>  
> @@ -830,6 +831,21 @@ static void info_opt(int level, int type, void *ptr, int len)
>  		break;
>  	case 0x0003:
>  		printf("Fixed channel list\n");
> +		list = get_val(ptr, 1);

We had discussion about this with Mat Martineau and agreed that we read 8
octets (there is one bit in 8th octet - AMP test manager)

> +		if (parser.flags & DUMP_VERBOSE) {
> +			if (list & L2CAP_FC_L2CAP) {
> +				p_indent(level + 1, 0);
> +				printf("L2CAP\n");
> +			}
> +			if (list & L2CAP_FC_CONNLESS) {
> +				p_indent(level + 1, 0);
> +				printf("CONNLESS\n");
> +			}
> +			if (list & L2CAP_FC_A2MP) {
> +				p_indent(level + 1, 0);
> +				printf("A2MP\n");
> +			}
> +		}

I know that this is common in hcidump but I do not like current approach.
I have sent similar patch and the difference (beyond mentioned above) is
that I define decode table:

+static struct features l2cap_fix_chan[] = {
+	{ "L2CAP Signalling Channel",		L2CAP_FC_L2CAP		},
+	{ "L2CAP Connless",			L2CAP_FC_CONNLESS	},
+	{ "AMP Manager Protocol",		L2CAP_FC_A2MP		},
+	{ 0 }
+};

then:

+		if (parser.flags & DUMP_VERBOSE)
+			for (i=0; l2cap_fix_chan[i].name; i++)
+				if (fc_mask & l2cap_fix_chan[i].flag) {
+					p_indent(level + 1, 0);
+					printf("%s\n", l2cap_fix_chan[i].name);
+				}

http://www.spinics.net/lists/linux-bluetooth/msg17247.html

This is the way how it is done is wireshark network packet analyzer.

Then if you want to add one extra feature (like AMP test manager) => you
just add new table entry. Otherwise you have to create new "if" branch.

Best regards 
Andrei Emeltchenko 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] Add parsing of A2MP signals
  2011-10-21 23:30 ` [PATCH 2/4] Add parsing of A2MP signals Peter Krystad
  2011-10-24  7:34   ` Andrei Emeltchenko
@ 2011-10-26 13:33   ` Andrei Emeltchenko
  2011-10-26 18:49     ` Peter Krystad
  1 sibling, 1 reply; 10+ messages in thread
From: Andrei Emeltchenko @ 2011-10-26 13:33 UTC (permalink / raw)
  To: Peter Krystad; +Cc: linux-bluetooth

Hi Peter,

On Fri, Oct 21, 2011 at 04:30:00PM -0700, Peter Krystad wrote:
...
> @@ -923,6 +1004,240 @@ static inline void move_cfm_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm
>  	printf("Move cfm rsp: icid 0x%4.4x\n", icid);
>  }
>  
> +static inline void amp_command_rej(int level, struct frame *frm)
> +{
> +	amp_cmd_rej_parms *h = frm->ptr;
> +	uint16_t reason = btohs(h->reason);
> +
> +	if (p_filter(FILT_A2MP))
> +		return;
> +
> +	printf("Command Reject: reason (%d)- ", reason);
> +	p_indent(level + 1, frm);

This doesn't make sense to use p_indent if you print on the same line.
Maybe you forgot "\n" ?

> +	printf("%s\n", ampreason2str(reason));
> +}
> +

Best regards 
Andrei Emeltchenko 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/4] Add parsing of A2MP signals
  2011-10-26 13:33   ` Andrei Emeltchenko
@ 2011-10-26 18:49     ` Peter Krystad
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Krystad @ 2011-10-26 18:49 UTC (permalink / raw)
  To: 'Andrei Emeltchenko'; +Cc: linux-bluetooth


Hi Andrei,

> >
> > +static inline void amp_command_rej(int level, struct frame *frm)
> > +{
> > +	amp_cmd_rej_parms *h = frm->ptr;
> > +	uint16_t reason = btohs(h->reason);
> > +
> > +	if (p_filter(FILT_A2MP))
> > +		return;
> > +
> > +	printf("Command Reject: reason (%d)- ", reason);
> > +	p_indent(level + 1, frm);
> 
> This doesn't make sense to use p_indent if you print on the same line.
> Maybe you forgot "\n" ?
> 
> > +	printf("%s\n", ampreason2str(reason));
> > +}
> > +
> 

Will add a '\n'. 

I'll repost this patch set after the bluez header patchset is approved.

Peter.

--Peter Krystad
  Employee of Qualcomm Innovation Center, Inc.
  Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-10-26 18:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-21 23:29 [PATCH 0/4] Add parsing of BT 3.0+HS signalling Peter Krystad
2011-10-21 23:29 ` [PATCH 1/4] Add parsing of L2CAP Create/Move Channel signals Peter Krystad
2011-10-22  7:21   ` Marcel Holtmann
2011-10-21 23:30 ` [PATCH 2/4] Add parsing of A2MP signals Peter Krystad
2011-10-24  7:34   ` Andrei Emeltchenko
2011-10-26 13:33   ` Andrei Emeltchenko
2011-10-26 18:49     ` Peter Krystad
2011-10-21 23:30 ` [PATCH 3/4] Add parsing of L2CAP Fixed Channel list Peter Krystad
2011-10-24  7:51   ` Andrei Emeltchenko
2011-10-21 23:30 ` [PATCH 4/4] Minor cleanup of indentation in output Peter Krystad

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).