All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support
@ 2018-07-11  9:31 Jaganath Kanakkassery
  2018-07-11  9:31 ` [PATCH v4 01/13] Bluetooth: Define default phys in hdev and set 1M as default Jaganath Kanakkassery
                   ` (12 more replies)
  0 siblings, 13 replies; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

Implemented Get, Set PHY Configuration and setting of PHY in
Advertising. Also implemented extended advertising,
scanning and connection.

v2: Fixed kbuild warnings
v3: Added BREDR packet types in PHY Configurtion commands and events
v4: Added default phys as variable in hdev and removed same from hci flags

Jaganath Kanakkassery (13):
  Bluetooth: Define default phys in hdev and set 1M as default
  Bluetooth: Implement Get PHY Configuration mgmt command
  Bluetooth: Implement Set PHY Confguration command
  Bluetooth: Set Scan PHYs based on selected PHYs by user
  Bluetooth: Handle extended ADV PDU types
  Bluetooth: Use selected PHYs in extended connect
  Bluetooth: Read no of adv sets during init
  Bluetooth: Impmlement extended adv enable
  Bluetooth: Use Set ext adv/scan rsp data if controller supports
  Bluetooth: Implement disable and removal of adv instance
  Bluetooth: Use ext adv for directed adv
  Bluetooth: Implement Set ADV set random address
  Bluetooth: Implement secondary advertising on different PHYs

 include/net/bluetooth/hci.h      | 116 +++++++++-
 include/net/bluetooth/hci_core.h |  21 ++
 include/net/bluetooth/mgmt.h     |  55 +++++
 net/bluetooth/hci_conn.c         | 153 +++++++++----
 net/bluetooth/hci_core.c         |  25 ++-
 net/bluetooth/hci_event.c        | 182 ++++++++++++++--
 net/bluetooth/hci_request.c      | 456 ++++++++++++++++++++++++++++++++++-----
 net/bluetooth/hci_request.h      |   8 +
 net/bluetooth/hci_sock.c         |   1 +
 net/bluetooth/mgmt.c             | 420 +++++++++++++++++++++++++++++++++++-
 10 files changed, 1314 insertions(+), 123 deletions(-)

-- 
2.7.4


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

* [PATCH v4 01/13] Bluetooth: Define default phys in hdev and set 1M as default
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 16:47   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command Jaganath Kanakkassery
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

1M would be set as default and same would be set during power on
if controller support SetDefaultPHY.

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h      | 4 ++++
 include/net/bluetooth/hci_core.h | 3 +++
 net/bluetooth/hci_core.c         | 9 +++++----
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 73e48be..664fe1e 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1514,6 +1514,10 @@ struct hci_cp_le_set_default_phy {
 	__u8    rx_phys;
 } __packed;
 
+#define HCI_LE_SET_PHY_1M		0x01
+#define HCI_LE_SET_PHY_2M		0x02
+#define HCI_LE_SET_PHY_CODED		0x04
+
 #define HCI_OP_LE_SET_EXT_SCAN_PARAMS   0x2041
 struct hci_cp_le_set_ext_scan_params {
 	__u8    own_addr_type;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a744535..71f79df 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -315,6 +315,9 @@ struct hci_dev {
 	unsigned long	sco_last_tx;
 	unsigned long	le_last_tx;
 
+	__u8		le_tx_def_phys;
+	__u8		le_rx_def_phys;
+
 	struct workqueue_struct	*workqueue;
 	struct workqueue_struct	*req_workqueue;
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f5c21004..432f89f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -830,10 +830,9 @@ static int hci_init4_req(struct hci_request *req, unsigned long opt)
 	if (hdev->commands[35] & 0x20) {
 		struct hci_cp_le_set_default_phy cp;
 
-		/* No transmitter PHY or receiver PHY preferences */
-		cp.all_phys = 0x03;
-		cp.tx_phys = 0;
-		cp.rx_phys = 0;
+		cp.all_phys = 0x00;
+		cp.tx_phys = hdev->le_tx_def_phys;
+		cp.rx_phys = hdev->le_rx_def_phys;
 
 		hci_req_add(req, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(cp), &cp);
 	}
@@ -3027,6 +3026,8 @@ struct hci_dev *hci_alloc_dev(void)
 	hdev->le_max_tx_time = 0x0148;
 	hdev->le_max_rx_len = 0x001b;
 	hdev->le_max_rx_time = 0x0148;
+	hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
+	hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M;
 
 	hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
 	hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT;
-- 
2.7.4


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

* [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
  2018-07-11  9:31 ` [PATCH v4 01/13] Bluetooth: Define default phys in hdev and set 1M as default Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 17:00   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command Jaganath Kanakkassery
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This commands basically retrieve the supported packet types of
BREDR and supported PHYs of the controller.

BR_1M_1SLOT, LE_1M_TX and LE_1M_RX would be supported by default.
Other PHYs are supported based on the local features.

@ MGMT Command: Get PHY Configuration (0x0044) plen 0
@ MGMT Event: Command Complete (0x0001) plen 15
      Get PHY Configuration (0x0044) plen 12
        Status: Success (0x00)
        Supported PHYs: 0x7fff
          BR 1M 1SLOT
          BR 1M 3SLOT
          BR 1M 5SLOT
          EDR 2M 1SLOT
          EDR 2M 3SLOT
          EDR 2M 5SLOT
          EDR 3M 1SLOT
          EDR 3M 3SLOT
          EDR 3M 5SLOT
          LE 1M TX
          LE 1M RX
          LE 2M TX
          LE 2M RX
          LE CODED TX
          LE CODED RX
        Configurable PHYs: 0x79fe
          BR 1M 3SLOT
          BR 1M 5SLOT
          EDR 2M 1SLOT
          EDR 2M 3SLOT
          EDR 2M 5SLOT
          EDR 3M 1SLOT
          EDR 3M 3SLOT
          EDR 3M 5SLOT
          LE 2M TX
          LE 2M RX
          LE CODED TX
          LE CODED RX
        Selected PHYs: 0x07ff
          BR 1M 1SLOT
          BR 1M 3SLOT
          BR 1M 5SLOT
          EDR 2M 1SLOT
          EDR 2M 3SLOT
          EDR 2M 5SLOT
          EDR 3M 1SLOT
          EDR 3M 3SLOT
          EDR 3M 5SLOT
          LE 1M TX
          LE 1M RX

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h      |  14 ++++
 include/net/bluetooth/hci_core.h |   4 ++
 include/net/bluetooth/mgmt.h     |  24 +++++++
 net/bluetooth/mgmt.c             | 149 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 191 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 664fe1e..89bf800 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -291,6 +291,14 @@ enum {
 #define HCI_DH3		0x0800
 #define HCI_DH5		0x8000
 
+/* HCI packet types inverted masks */
+#define HCI_2DH1	0x0002
+#define HCI_3DH1	0x0004
+#define HCI_2DH3	0x0100
+#define HCI_3DH3	0x0200
+#define HCI_2DH5	0x1000
+#define HCI_3DH5	0x2000
+
 #define HCI_HV1		0x0020
 #define HCI_HV2		0x0040
 #define HCI_HV3		0x0080
@@ -354,6 +362,8 @@ enum {
 #define LMP_PCONTROL	0x04
 #define LMP_TRANSPARENT	0x08
 
+#define LMP_EDR_2M		0x02
+#define LMP_EDR_3M		0x04
 #define LMP_RSSI_INQ	0x40
 #define LMP_ESCO	0x80
 
@@ -361,7 +371,9 @@ enum {
 #define LMP_EV5		0x02
 #define LMP_NO_BREDR	0x20
 #define LMP_LE		0x40
+#define LMP_EDR_3SLOT	0x80
 
+#define LMP_EDR_5SLOT	0x01
 #define LMP_SNIFF_SUBR	0x02
 #define LMP_PAUSE_ENC	0x04
 #define LMP_EDR_ESCO_2M	0x20
@@ -399,6 +411,8 @@ enum {
 #define HCI_LE_PING			0x10
 #define HCI_LE_DATA_LEN_EXT		0x20
 #define HCI_LE_EXT_SCAN_POLICY		0x80
+#define HCI_LE_PHY_2M			0x01
+#define HCI_LE_PHY_CODED		0x08
 #define HCI_LE_CHAN_SEL_ALG2		0x40
 
 /* Connection modes */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 71f79df..a64d13f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1141,6 +1141,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
 #define lmp_ext_feat_capable(dev)  ((dev)->features[0][7] & LMP_EXTFEATURES)
 #define lmp_transp_capable(dev)    ((dev)->features[0][2] & LMP_TRANSPARENT)
+#define lmp_edr_2m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_2M)
+#define lmp_edr_3m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_3M)
+#define lmp_edr_3slot_capable(dev) ((dev)->features[0][4] & LMP_EDR_3SLOT)
+#define lmp_edr_5slot_capable(dev) ((dev)->features[0][5] & LMP_EDR_5SLOT)
 
 /* ----- Extended LMP capabilities ----- */
 #define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_MASTER)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index e7303ee..16dddb1 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -604,6 +604,30 @@ struct mgmt_cp_set_appearance {
 } __packed;
 #define MGMT_SET_APPEARANCE_SIZE	2
 
+#define MGMT_OP_GET_PHY_CONFIGURATION	0x0044
+#define MGMT_GET_PHY_CONFIGURATION_SIZE		0
+struct mgmt_rp_get_phy_confguration {
+	__le32	supported_phys;
+	__le32	configurable_phys;
+	__le32	selected_phys;
+} __packed;
+
+#define MGMT_PHY_BR_1M_1SLOT	0x00000001
+#define MGMT_PHY_BR_1M_3SLOT	0x00000002
+#define MGMT_PHY_BR_1M_5SLOT	0x00000004
+#define MGMT_PHY_EDR_2M_1SLOT	0x00000008
+#define MGMT_PHY_EDR_2M_3SLOT	0x00000010
+#define MGMT_PHY_EDR_2M_5SLOT	0x00000020
+#define MGMT_PHY_EDR_3M_1SLOT	0x00000040
+#define MGMT_PHY_EDR_3M_3SLOT	0x00000080
+#define MGMT_PHY_EDR_3M_5SLOT	0x00000100
+#define MGMT_PHY_LE_1M_TX		0x00000200
+#define MGMT_PHY_LE_1M_RX		0x00000400
+#define MGMT_PHY_LE_2M_TX		0x00000800
+#define MGMT_PHY_LE_2M_RX		0x00001000
+#define MGMT_PHY_LE_CODED_TX	0x00002000
+#define MGMT_PHY_LE_CODED_RX	0x00004000
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8a80d48..4a31d4d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -617,6 +617,126 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev,
 				 &rp, sizeof(rp));
 }
 
+static u32 get_supported_phys(struct hci_dev *hdev)
+{
+	u32 supported_phys = 0;
+
+	if (lmp_bredr_capable(hdev)) {
+		supported_phys |= MGMT_PHY_BR_1M_1SLOT;
+
+		if (hdev->features[0][0] & LMP_3SLOT)
+			supported_phys |= MGMT_PHY_BR_1M_3SLOT;
+
+		if (hdev->features[0][0] & LMP_5SLOT)
+			supported_phys |= MGMT_PHY_BR_1M_5SLOT;
+
+		if (lmp_edr_2m_capable(hdev)) {
+			supported_phys |= MGMT_PHY_EDR_2M_1SLOT;
+
+			if (lmp_edr_3slot_capable(hdev))
+				supported_phys |= MGMT_PHY_EDR_2M_3SLOT;
+
+			if (lmp_edr_5slot_capable(hdev))
+				supported_phys |= MGMT_PHY_EDR_2M_5SLOT;
+
+			if (lmp_edr_3m_capable(hdev)) {
+				supported_phys |= MGMT_PHY_EDR_3M_1SLOT;
+
+				if (lmp_edr_3slot_capable(hdev))
+					supported_phys |= MGMT_PHY_EDR_3M_3SLOT;
+
+				if (lmp_edr_5slot_capable(hdev))
+					supported_phys |= MGMT_PHY_EDR_3M_5SLOT;
+			}
+		}
+	}
+
+	if (lmp_le_capable(hdev)) {
+		supported_phys |= MGMT_PHY_LE_1M_TX;
+		supported_phys |= MGMT_PHY_LE_1M_RX;
+
+		if (hdev->le_features[1] & HCI_LE_PHY_2M) {
+			supported_phys |= MGMT_PHY_LE_2M_TX;
+			supported_phys |= MGMT_PHY_LE_2M_RX;
+		}
+		if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
+			supported_phys |= MGMT_PHY_LE_CODED_TX;
+			supported_phys |= MGMT_PHY_LE_CODED_RX;
+		}
+	}
+
+	return supported_phys;
+}
+
+static u32 get_selected_phys(struct hci_dev *hdev)
+{
+	u32 selected_phys = 0;
+
+	if (lmp_bredr_capable(hdev)) {
+		selected_phys |= MGMT_PHY_BR_1M_1SLOT;
+
+		if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
+			selected_phys |= MGMT_PHY_BR_1M_3SLOT;
+
+		if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
+			selected_phys |= MGMT_PHY_BR_1M_5SLOT;
+
+		if (lmp_edr_2m_capable(hdev)) {
+			if (!(hdev->pkt_type & HCI_2DH1))
+				selected_phys |= MGMT_PHY_EDR_2M_1SLOT;
+
+			if (lmp_edr_3slot_capable(hdev) &&
+				!(hdev->pkt_type & HCI_2DH3))
+				selected_phys |= MGMT_PHY_EDR_2M_3SLOT;
+
+			if (lmp_edr_5slot_capable(hdev) &&
+				!(hdev->pkt_type & HCI_2DH5))
+				selected_phys |= MGMT_PHY_EDR_2M_5SLOT;
+
+			if (lmp_edr_3m_capable(hdev)) {
+				if (!(hdev->pkt_type & HCI_3DH1))
+					selected_phys |= MGMT_PHY_EDR_3M_1SLOT;
+
+				if (lmp_edr_3slot_capable(hdev) &&
+					!(hdev->pkt_type & HCI_3DH3))
+					selected_phys |= MGMT_PHY_EDR_3M_3SLOT;
+
+				if (lmp_edr_5slot_capable(hdev) &&
+					!(hdev->pkt_type & HCI_3DH5))
+					selected_phys |= MGMT_PHY_EDR_3M_5SLOT;
+			}
+		}
+	}
+
+	if (lmp_le_capable(hdev)) {
+		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
+			selected_phys |= MGMT_PHY_LE_1M_TX;
+
+		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
+			selected_phys |= MGMT_PHY_LE_1M_RX;
+
+		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
+			selected_phys |= MGMT_PHY_LE_2M_TX;
+
+		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
+			selected_phys |= MGMT_PHY_LE_2M_RX;
+
+		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
+			selected_phys |= MGMT_PHY_LE_CODED_TX;
+
+		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
+			selected_phys |= MGMT_PHY_LE_CODED_RX;
+	}
+
+	return selected_phys;
+}
+
+static u32 get_configurable_phys(struct hci_dev *hdev)
+{
+	return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
+			~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
+}
+
 static u32 get_supported_settings(struct hci_dev *hdev)
 {
 	u32 settings = 0;
@@ -654,6 +774,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
 	    hdev->set_bdaddr)
 		settings |= MGMT_SETTING_CONFIGURATION;
 
+	if (get_supported_phys(hdev) & ~(MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_LE_1M_TX |
+					MGMT_PHY_LE_1M_RX))
+		settings |= MGMT_SETTING_PHY_CONFIGURATION;
+
 	return settings;
 }
 
@@ -722,6 +846,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
 			settings |= MGMT_SETTING_STATIC_ADDRESS;
 	}
 
+	if (phys_configured(hdev))
+		settings |= MGMT_SETTING_PHY_CONFIGURATION;
+
 	return settings;
 }
 
@@ -3184,6 +3311,27 @@ static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
 	return err;
 }
 
+static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
+				 void *data, u16 len)
+{
+	struct mgmt_rp_get_phy_confguration rp;
+
+	BT_DBG("sock %p %s", sk, hdev->name);
+
+	hci_dev_lock(hdev);
+
+	memset(&rp, 0, sizeof(rp));
+
+	rp.supported_phys = cpu_to_le32(get_supported_phys(hdev));
+	rp.selected_phys = cpu_to_le32(get_selected_phys(hdev));
+	rp.configurable_phys = cpu_to_le32(get_configurable_phys(hdev));
+
+	hci_dev_unlock(hdev);
+
+	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_PHY_CONFIGURATION, 0,
+				 &rp, sizeof(rp));
+}
+
 static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
 				         u16 opcode, struct sk_buff *skb)
 {
@@ -6544,6 +6692,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
 	{ read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE,
 						HCI_MGMT_UNTRUSTED },
 	{ set_appearance,	   MGMT_SET_APPEARANCE_SIZE },
+	{ get_phy_configuration,   MGMT_GET_PHY_CONFIGURATION_SIZE },
 };
 
 void mgmt_index_added(struct hci_dev *hdev)
-- 
2.7.4

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

* [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
  2018-07-11  9:31 ` [PATCH v4 01/13] Bluetooth: Define default phys in hdev and set 1M as default Jaganath Kanakkassery
  2018-07-11  9:31 ` [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 17:18   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 04/13] Bluetooth: Set Scan PHYs based on selected PHYs by user Jaganath Kanakkassery
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This enables user to set phys which will be used in all subsequent
connections. Also host will use the same in LE scanning as well.

This patch also implements PHY Changed event which will be
triggered whenever default PHYs change.

This also adds PHY_CONFIGURATION to mgmt settings which set
in the supported settings if controller supports 2/3 slot
or 2M/#M in BREDR controller and 2M or CODED in case of LE
and set in current settings if any of them is selected

@ MGMT Command: Set PHY Configuration (0x0045) plen 4
        Selected PHYs: 0x7fff
          BR 1M 1SLOT
          BR 1M 3SLOT
          BR 1M 5SLOT
          EDR 2M 1SLOT
          EDR 2M 3SLOT
          EDR 2M 5SLOT
          EDR 3M 1SLOT
          EDR 3M 3SLOT
          EDR 3M 5SLOT
          LE 1M TX
          LE 1M RX
          LE 2M TX
          LE 2M RX
          LE CODED TX
          LE CODED RX
< HCI Command: LE Set Default PHY (0x08|0x0031) plen 3
        All PHYs preference: 0x00
        TX PHYs preference: 0x07
          LE 1M
          LE 2M
          LE Coded
        RX PHYs preference: 0x07
          LE 1M
          LE 2M
          LE Coded
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Default PHY (0x08|0x0031) ncmd 1
        Status: Success (0x00)
@ MGMT Event: Command Complete (0x0001) plen 3
      Set PHY Configuration (0x0045) plen 0
        Status: Success (0x00)
@ MGMT Event: PHY Configuration Changed (0x0026) plen 4
        Selected PHYs: 0x7fff
          BR 1M 1SLOT
          BR 1M 3SLOT
          BR 1M 5SLOT
          EDR 2M 1SLOT
          EDR 2M 3SLOT
          EDR 2M 5SLOT
          EDR 3M 1SLOT
          EDR 3M 3SLOT
          EDR 3M 5SLOT
          LE 1M TX
          LE 1M RX
          LE 2M TX
          LE 2M RX
          LE CODED TX
          LE CODED RX

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h      |   1 +
 include/net/bluetooth/hci_core.h |   1 +
 include/net/bluetooth/mgmt.h     |  25 +++++
 net/bluetooth/hci_core.c         |   4 +
 net/bluetooth/hci_event.c        |  26 +++++
 net/bluetooth/hci_sock.c         |   1 +
 net/bluetooth/mgmt.c             | 221 +++++++++++++++++++++++++++++++++++++++
 7 files changed, 279 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 89bf800..d0f7657 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -214,6 +214,7 @@ enum {
 	HCI_MGMT_DEV_CLASS_EVENTS,
 	HCI_MGMT_LOCAL_NAME_EVENTS,
 	HCI_MGMT_OOB_DATA_EVENTS,
+	HCI_MGMT_PHY_CHANGED_EVENTS,
 };
 
 /*
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a64d13f..ab5d494 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1544,6 +1544,7 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
 			    u8 instance);
 void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
 			      u8 instance);
+int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
 
 u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
 		      u16 to_multiplier);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 16dddb1..047e98d 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -101,6 +101,7 @@ struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_PRIVACY		0x00002000
 #define MGMT_SETTING_CONFIGURATION	0x00004000
 #define MGMT_SETTING_STATIC_ADDRESS	0x00008000
+#define MGMT_SETTING_PHY_CONFIGURATION  0x00010000
 
 #define MGMT_OP_READ_INFO		0x0004
 #define MGMT_READ_INFO_SIZE		0
@@ -628,6 +629,25 @@ struct mgmt_rp_get_phy_confguration {
 #define MGMT_PHY_LE_CODED_TX	0x00002000
 #define MGMT_PHY_LE_CODED_RX	0x00004000
 
+#define MGMT_PHY_BREDR_MASK (MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_BR_1M_3SLOT | \
+				MGMT_PHY_BR_1M_5SLOT | MGMT_PHY_EDR_2M_1SLOT | \
+				MGMT_PHY_EDR_2M_3SLOT | MGMT_PHY_EDR_2M_5SLOT | \
+				MGMT_PHY_EDR_3M_1SLOT | MGMT_PHY_EDR_3M_3SLOT | \
+				MGMT_PHY_EDR_3M_5SLOT)
+#define MGMT_PHY_LE_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX | \
+				MGMT_PHY_LE_2M_TX | MGMT_PHY_LE_2M_RX | \
+				MGMT_PHY_LE_CODED_TX | MGMT_PHY_LE_CODED_RX)
+#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
+			     MGMT_PHY_LE_CODED_TX)
+#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \
+			     MGMT_PHY_LE_CODED_RX)
+
+#define MGMT_OP_SET_PHY_CONFIGURATION	0x0045
+#define MGMT_SET_PHY_CONFIGURATION_SIZE		4
+struct mgmt_cp_set_phy_confguration {
+	__le32	selected_phys;
+} __packed;
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
@@ -848,3 +868,8 @@ struct mgmt_ev_ext_info_changed {
 	__le16	eir_len;
 	__u8	eir[0];
 } __packed;
+
+#define MGMT_EV_PHY_CONFIGURATION_CHANGED	0x0026
+struct mgmt_ev_phy_configuration_changed {
+	__le32	selected_phys;
+} __packed;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 432f89f..0d88dc9 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1924,7 +1924,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
 		break;
 
 	case HCISETPTYPE:
+		if (hdev->pkt_type == ((__u16) dr.dev_opt))
+			break;
+
 		hdev->pkt_type = (__u16) dr.dev_opt;
+		mgmt_phy_configuration_changed(hdev, NULL);
 		break;
 
 	case HCISETACLMTU:
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6819215..6942315 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1042,6 +1042,28 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status = *((__u8 *) skb->data);
+	struct hci_cp_le_set_default_phy *cp;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	if (status)
+		return;
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
+	if (!cp)
+		return;
+
+	hci_dev_lock(hdev);
+
+	hdev->le_tx_def_phys = cp->tx_phys;
+	hdev->le_rx_def_phys = cp->rx_phys;
+
+	hci_dev_unlock(hdev);
+}
+
 static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 *sent, status = *((__u8 *) skb->data);
@@ -3163,6 +3185,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
 		hci_cc_le_set_ext_scan_enable(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_DEFAULT_PHY:
+		hci_cc_le_set_default_phy(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
 		break;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 1506e16..476916c 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1328,6 +1328,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
 			hci_sock_set_flag(sk, HCI_MGMT_SETTING_EVENTS);
 			hci_sock_set_flag(sk, HCI_MGMT_DEV_CLASS_EVENTS);
 			hci_sock_set_flag(sk, HCI_MGMT_LOCAL_NAME_EVENTS);
+			hci_sock_set_flag(sk, HCI_MGMT_PHY_CHANGED_EVENTS);
 		}
 		break;
 	}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4a31d4d..1c2ed42 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -737,6 +737,23 @@ static u32 get_configurable_phys(struct hci_dev *hdev)
 			~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
 }
 
+static bool phys_configured(struct hci_dev *hdev)
+{
+	u32 selected_phys = get_selected_phys(hdev);
+	u32 supported_phys = get_supported_phys(hdev);
+
+	/* If any of BREDR supported PHYs are deselected or
+	 *  LE PHYs other than 1M are selected
+	 */
+	if (((supported_phys & MGMT_PHY_BREDR_MASK) !=
+		 (selected_phys & MGMT_PHY_BREDR_MASK)) ||
+		((selected_phys & MGMT_PHY_LE_MASK) &
+		  ~(MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX)))
+		return true;
+
+	return false;
+}
+
 static u32 get_supported_settings(struct hci_dev *hdev)
 {
 	u32 settings = 0;
@@ -3332,6 +3349,209 @@ static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
 				 &rp, sizeof(rp));
 }
 
+int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
+{
+	struct mgmt_ev_phy_configuration_changed ev;
+
+	memset(&ev, 0, sizeof(ev));
+
+	ev.selected_phys = cpu_to_le32(get_selected_phys(hdev));
+
+	return mgmt_limited_event(MGMT_EV_PHY_CONFIGURATION_CHANGED, hdev, &ev,
+				  sizeof(ev), HCI_MGMT_PHY_CHANGED_EVENTS,
+				  skip);
+}
+
+static void set_default_phy_complete(struct hci_dev *hdev, u8 status,
+				     u16 opcode, struct sk_buff *skb)
+{
+	struct mgmt_cp_set_phy_confguration *cp;
+	struct mgmt_pending_cmd *cmd;
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	cmd = pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev);
+	if (!cmd)
+		goto unlock;
+
+	cp = cmd->param;
+
+	if (status) {
+		mgmt_cmd_status(cmd->sk, hdev->id,
+				MGMT_OP_SET_PHY_CONFIGURATION,
+				mgmt_status(status));
+	} else {
+		mgmt_cmd_complete(cmd->sk, hdev->id,
+				  MGMT_OP_SET_PHY_CONFIGURATION, 0,
+				  NULL, 0);
+
+		mgmt_phy_configuration_changed(hdev, cmd->sk);
+		new_settings(hdev, cmd->sk);
+	}
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
+static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
+				 void *data, u16 len)
+{
+	struct mgmt_cp_set_phy_confguration *cp = data;
+	struct hci_cp_le_set_default_phy cp_phy;
+	struct mgmt_pending_cmd *cmd;
+	struct hci_request req;
+	u32 selected_phys, configurable_phys, supported_phys, unconfigure_phys;
+	u16 pkt_type = (HCI_DH1 | HCI_DM1);
+	bool changed = false;
+	int err;
+
+	BT_DBG("sock %p %s", sk, hdev->name);
+
+	configurable_phys = get_configurable_phys(hdev);
+	supported_phys = get_supported_phys(hdev);
+	selected_phys = __le32_to_cpu(cp->selected_phys);
+
+	if (selected_phys & ~supported_phys)
+		return mgmt_cmd_status(sk, hdev->id,
+				       MGMT_OP_SET_PHY_CONFIGURATION,
+				       MGMT_STATUS_INVALID_PARAMS);
+
+	unconfigure_phys = supported_phys & ~configurable_phys;
+
+	if ((selected_phys & unconfigure_phys) != unconfigure_phys)
+		return mgmt_cmd_status(sk, hdev->id,
+				       MGMT_OP_SET_PHY_CONFIGURATION,
+				       MGMT_STATUS_INVALID_PARAMS);
+
+	if (selected_phys == get_selected_phys(hdev))
+		return mgmt_cmd_complete(sk, hdev->id,
+					 MGMT_OP_SET_PHY_CONFIGURATION,
+					 0, NULL, 0);
+
+	hci_dev_lock(hdev);
+
+	if (!hdev_is_powered(hdev)) {
+		err = mgmt_cmd_status(sk, hdev->id,
+				      MGMT_OP_SET_PHY_CONFIGURATION,
+				      MGMT_STATUS_REJECTED);
+		goto unlock;
+	}
+
+	if (pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) {
+		err = mgmt_cmd_status(sk, hdev->id,
+				      MGMT_OP_SET_PHY_CONFIGURATION,
+				      MGMT_STATUS_BUSY);
+		goto unlock;
+	}
+
+	if (selected_phys & MGMT_PHY_BR_1M_3SLOT)
+		pkt_type |= (HCI_DH3 | HCI_DM3);
+	else
+		pkt_type &= ~(HCI_DH3 | HCI_DM3);
+
+	if (selected_phys & MGMT_PHY_BR_1M_5SLOT)
+		pkt_type |= (HCI_DH5 | HCI_DM5);
+	else
+		pkt_type &= ~(HCI_DH5 | HCI_DM5);
+
+	if (selected_phys & MGMT_PHY_EDR_2M_1SLOT)
+		pkt_type &= ~HCI_2DH1;
+	else
+		pkt_type |= HCI_2DH1;
+
+	if (selected_phys & MGMT_PHY_EDR_2M_3SLOT)
+		pkt_type &= ~HCI_2DH3;
+	else
+		pkt_type |= HCI_2DH3;
+
+	if (selected_phys & MGMT_PHY_EDR_2M_5SLOT)
+		pkt_type &= ~HCI_2DH5;
+	else
+		pkt_type |= HCI_2DH5;
+
+	if (selected_phys & MGMT_PHY_EDR_3M_1SLOT)
+		pkt_type &= ~HCI_3DH1;
+	else
+		pkt_type |= HCI_3DH1;
+
+	if (selected_phys & MGMT_PHY_EDR_3M_3SLOT)
+		pkt_type &= ~HCI_3DH3;
+	else
+		pkt_type |= HCI_3DH3;
+
+	if (selected_phys & MGMT_PHY_EDR_3M_5SLOT)
+		pkt_type &= ~HCI_3DH5;
+	else
+		pkt_type |= HCI_3DH5;
+
+	if (pkt_type != hdev->pkt_type) {
+		hdev->pkt_type = pkt_type;
+		changed = true;
+	}
+
+	if ((selected_phys & MGMT_PHY_LE_MASK) ==
+		(get_selected_phys(hdev) & MGMT_PHY_LE_MASK)) {
+		if (changed)
+			mgmt_phy_configuration_changed(hdev, sk);
+
+		err = mgmt_cmd_complete(sk, hdev->id,
+					MGMT_OP_SET_PHY_CONFIGURATION,
+					0, NULL, 0);
+
+		goto unlock;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
+			       len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto unlock;
+	}
+
+	hci_req_init(&req, hdev);
+
+	memset(&cp_phy, 0, sizeof(cp_phy));
+
+	if (!(selected_phys & MGMT_PHY_LE_TX_MASK))
+		cp_phy.all_phys |= 0x01;
+
+	if (!(selected_phys & MGMT_PHY_LE_RX_MASK))
+		cp_phy.all_phys |= 0x02;
+
+	if (selected_phys & MGMT_PHY_LE_1M_TX)
+		cp_phy.tx_phys |= HCI_LE_SET_PHY_1M;
+
+	if (selected_phys & MGMT_PHY_LE_2M_TX)
+		cp_phy.tx_phys |= HCI_LE_SET_PHY_2M;
+
+	if (selected_phys & MGMT_PHY_LE_CODED_TX)
+		cp_phy.tx_phys |= HCI_LE_SET_PHY_CODED;
+
+	if (selected_phys & MGMT_PHY_LE_1M_RX)
+		cp_phy.rx_phys |= HCI_LE_SET_PHY_1M;
+
+	if (selected_phys & MGMT_PHY_LE_2M_RX)
+		cp_phy.rx_phys |= HCI_LE_SET_PHY_2M;
+
+	if (selected_phys & MGMT_PHY_LE_CODED_RX)
+		cp_phy.rx_phys |= HCI_LE_SET_PHY_CODED;
+
+	hci_req_add(&req, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(cp_phy), &cp_phy);
+
+	err = hci_req_run_skb(&req, set_default_phy_complete);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+
+	return err;
+}
+
 static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
 				         u16 opcode, struct sk_buff *skb)
 {
@@ -6693,6 +6913,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
 						HCI_MGMT_UNTRUSTED },
 	{ set_appearance,	   MGMT_SET_APPEARANCE_SIZE },
 	{ get_phy_configuration,   MGMT_GET_PHY_CONFIGURATION_SIZE },
+	{ set_phy_configuration,   MGMT_SET_PHY_CONFIGURATION_SIZE },
 };
 
 void mgmt_index_added(struct hci_dev *hdev)
-- 
2.7.4

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

* [PATCH v4 04/13] Bluetooth: Set Scan PHYs based on selected PHYs by user
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (2 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 17:24   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types Jaganath Kanakkassery
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

Use the PHYs selected in Set Phy Configuration management command
while scanning.

< HCI Command: LE Set Extended Scan Parameters (0x08|0x0041) plen 13
        Own address type: Random (0x01)
        Filter policy: Accept all advertisement (0x00)
        PHYs: 0x05
        Entry 0: LE 1M
          Type: Active (0x01)
          Interval: 11.250 msec (0x0012)
          Window: 11.250 msec (0x0012)
        Entry 1: LE Coded
          Type: Active (0x01)
          Interval: 11.250 msec (0x0012)
          Window: 11.250 msec (0x0012)
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1
        Status: Success (0x00)
< HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6
        Extended scan: Enabled (0x01)
        Filter duplicates: Enabled (0x01)
        Duration: 0 msec (0x0000)
        Period: 0.00 sec (0x0000)
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Scan Enable (0x08|0x0042) ncmd 2
        Status: Success (0x00)

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h      |  4 +++-
 include/net/bluetooth/hci_core.h |  9 +++++++++
 net/bluetooth/hci_request.c      | 42 ++++++++++++++++++++++++++++------------
 3 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index d0f7657..3584632 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1541,7 +1541,9 @@ struct hci_cp_le_set_ext_scan_params {
 	__u8    data[0];
 } __packed;
 
-#define LE_SCAN_PHY_1M 0x01
+#define LE_SCAN_PHY_1M		0x01
+#define LE_SCAN_PHY_2M		0x02
+#define LE_SCAN_PHY_CODED	0x04
 
 struct hci_cp_le_scan_phy_params {
 	__u8    type;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ab5d494..33aab89e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1165,6 +1165,15 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define bredr_sc_enabled(dev)  (lmp_sc_capable(dev) && \
 				hci_dev_test_flag(dev, HCI_SC_ENABLED))
 
+#define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \
+		      ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M))
+
+#define scan_2m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_2M) || \
+		      ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_2M))
+
+#define scan_coded(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_CODED) || \
+		      ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED))
+
 /* Use ext scanning if set ext scan param and ext scan enable is supported */
 #define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \
 			   ((dev)->commands[37] & 0x40))
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index faf7c71..7f5950e 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -783,15 +783,13 @@ static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval,
 {
 	struct hci_dev *hdev = req->hdev;
 
-	/* Use ext scanning if set ext scan param and ext scan enable is
-	 * supported
-	 */
 	if (use_ext_scan(hdev)) {
 		struct hci_cp_le_set_ext_scan_params *ext_param_cp;
 		struct hci_cp_le_set_ext_scan_enable ext_enable_cp;
 		struct hci_cp_le_scan_phy_params *phy_params;
-		/* Ony single PHY (1M) is supported as of now */
-		u8 data[sizeof(*ext_param_cp) + sizeof(*phy_params) * 1];
+		u8 data[sizeof(*ext_param_cp) + sizeof(*phy_params) * 2];
+		u32 plen;
+		u8 scan_phys;
 
 		ext_param_cp = (void *)data;
 		phy_params = (void *)ext_param_cp->data;
@@ -799,16 +797,36 @@ static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval,
 		memset(ext_param_cp, 0, sizeof(*ext_param_cp));
 		ext_param_cp->own_addr_type = own_addr_type;
 		ext_param_cp->filter_policy = filter_policy;
-		ext_param_cp->scanning_phys = LE_SCAN_PHY_1M;
 
-		memset(phy_params, 0, sizeof(*phy_params));
-		phy_params->type = type;
-		phy_params->interval = cpu_to_le16(interval);
-		phy_params->window = cpu_to_le16(window);
+		plen = sizeof(*ext_param_cp);
+
+		if (scan_1m(hdev) || scan_2m(hdev))
+			ext_param_cp->scanning_phys |= LE_SCAN_PHY_1M;
+
+		if (scan_coded(hdev))
+			ext_param_cp->scanning_phys |= LE_SCAN_PHY_CODED;
+
+		scan_phys = ext_param_cp->scanning_phys;
+
+		while (scan_phys) {
+			if (!(scan_phys & 0x01)) {
+				scan_phys >>= 0x01;
+				continue;
+			}
+
+			memset(phy_params, 0, sizeof(*phy_params));
+			phy_params->type = type;
+			phy_params->interval = cpu_to_le16(interval);
+			phy_params->window = cpu_to_le16(window);
+
+			plen += sizeof(*phy_params);
+			phy_params++;
+
+			scan_phys >>= 0x01;
+		}
 
 		hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_PARAMS,
-			    sizeof(*ext_param_cp) + sizeof(*phy_params),
-			    ext_param_cp);
+			    plen, ext_param_cp);
 
 		memset(&ext_enable_cp, 0, sizeof(ext_enable_cp));
 		ext_enable_cp.enable = LE_SCAN_ENABLE;
-- 
2.7.4

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

* [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (3 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 04/13] Bluetooth: Set Scan PHYs based on selected PHYs by user Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 17:28   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 06/13] Bluetooth: Use selected PHYs in extended connect Jaganath Kanakkassery
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This patch defines the extended ADV types and handle it in ADV report.

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h |  8 ++++++++
 net/bluetooth/hci_event.c   | 49 +++++++++++++++++++++++++++++++--------------
 2 files changed, 42 insertions(+), 15 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 3584632..fcd1d57 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1977,6 +1977,14 @@ struct hci_ev_le_conn_complete {
 #define LE_LEGACY_SCAN_RSP_ADV		0x001b
 #define LE_LEGACY_SCAN_RSP_ADV_SCAN	0x001a
 
+/* Extended Advertising event types */
+#define LE_EXT_ADV_NON_CONN_IND		0x0000
+#define LE_EXT_ADV_CONN_IND		0x0001
+#define LE_EXT_ADV_SCAN_IND		0x0002
+#define LE_EXT_ADV_DIRECT_IND		0x0004
+#define LE_EXT_ADV_SCAN_RSP		0x0008
+#define LE_EXT_ADV_LEGACY_PDU		0x0010
+
 #define ADDR_LE_DEV_PUBLIC	0x00
 #define ADDR_LE_DEV_RANDOM	0x01
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6942315..027abe6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -5137,20 +5137,39 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static u8 convert_legacy_evt_type(u16 evt_type)
-{
-	switch (evt_type) {
-	case LE_LEGACY_ADV_IND:
-		return LE_ADV_IND;
-	case LE_LEGACY_ADV_DIRECT_IND:
-		return LE_ADV_DIRECT_IND;
-	case LE_LEGACY_ADV_SCAN_IND:
-		return LE_ADV_SCAN_IND;
-	case LE_LEGACY_NONCONN_IND:
-		return LE_ADV_NONCONN_IND;
-	case LE_LEGACY_SCAN_RSP_ADV:
-	case LE_LEGACY_SCAN_RSP_ADV_SCAN:
-		return LE_ADV_SCAN_RSP;
+static u8 convert_ext_evt_type(u16 evt_type)
+{
+	if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
+		switch (evt_type) {
+		case LE_LEGACY_ADV_IND:
+			return LE_ADV_IND;
+		case LE_LEGACY_ADV_DIRECT_IND:
+			return LE_ADV_DIRECT_IND;
+		case LE_LEGACY_ADV_SCAN_IND:
+			return LE_ADV_SCAN_IND;
+		case LE_LEGACY_NONCONN_IND:
+			return LE_ADV_NONCONN_IND;
+		case LE_LEGACY_SCAN_RSP_ADV:
+		case LE_LEGACY_SCAN_RSP_ADV_SCAN:
+			return LE_ADV_SCAN_RSP;
+		}
+	} else {
+		if (evt_type & LE_EXT_ADV_CONN_IND) {
+			if (evt_type & LE_EXT_ADV_DIRECT_IND)
+				return LE_ADV_DIRECT_IND;
+
+			return LE_ADV_IND;
+		}
+
+		if (evt_type & LE_EXT_ADV_SCAN_RSP)
+			return LE_ADV_SCAN_RSP;
+
+		if (evt_type & LE_EXT_ADV_SCAN_IND)
+			return LE_ADV_SCAN_IND;
+
+		if (evt_type == LE_EXT_ADV_NON_CONN_IND ||
+		    evt_type & LE_EXT_ADV_DIRECT_IND)
+			return LE_ADV_NONCONN_IND;
 	}
 
 	BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
@@ -5172,7 +5191,7 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		u16 evt_type;
 
 		evt_type = __le16_to_cpu(ev->evt_type);
-		legacy_evt_type = convert_legacy_evt_type(evt_type);
+		legacy_evt_type = convert_ext_evt_type(evt_type);
 		if (legacy_evt_type != LE_ADV_INVALID) {
 			process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
 					   ev->bdaddr_type, NULL, 0, ev->rssi,
-- 
2.7.4

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

* [PATCH v4 06/13] Bluetooth: Use selected PHYs in extended connect
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (4 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 17:30   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 07/13] Bluetooth: Read no of adv sets during init Jaganath Kanakkassery
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

Use the selected PHYs by Set PHY Configuration management command
in extended create connection.

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 net/bluetooth/hci_conn.c | 63 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 47 insertions(+), 16 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index cc967ca..5d421a2 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -777,8 +777,9 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
 	if (use_ext_conn(hdev)) {
 		struct hci_cp_le_ext_create_conn *cp;
 		struct hci_cp_le_ext_conn_param *p;
-		/* As of now only LE 1M is supported */
-		u8 data[sizeof(*cp) + sizeof(*p) * 1];
+		u8 data[sizeof(*cp) + sizeof(*p) * 3];
+		u8 init_phys;
+		u32 plen;
 
 		cp = (void *) data;
 		p = (void *) cp->data;
@@ -788,24 +789,54 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
 		bacpy(&cp->peer_addr, &conn->dst);
 		cp->peer_addr_type = conn->dst_type;
 		cp->own_addr_type = own_addr_type;
-		cp->phys = LE_SCAN_PHY_1M;
 
-		memset(p, 0, sizeof(*p));
+		if (scan_1m(hdev))
+			cp->phys |= LE_SCAN_PHY_1M;
 
-		/* Set window to be the same value as the interval to enable
-		 * continuous scanning.
-		 */
+		if (scan_2m(hdev))
+			cp->phys |= LE_SCAN_PHY_2M;
+
+		if (scan_coded(hdev))
+			cp->phys |= LE_SCAN_PHY_CODED;
+
+		init_phys = cp->phys;
+
+		plen = sizeof(*cp);
+
+		/* Use same param for all PHYs */
+		while (init_phys) {
+			u16 min_interval, max_interval, supv_timeout;
 
-		p->scan_interval = cpu_to_le16(hdev->le_scan_interval);
-		p->scan_window = p->scan_interval;
-		p->conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
-		p->conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
-		p->conn_latency = cpu_to_le16(conn->le_conn_latency);
-		p->supervision_timeout = cpu_to_le16(conn->le_supv_timeout);
-		p->min_ce_len = cpu_to_le16(0x0000);
-		p->max_ce_len = cpu_to_le16(0x0000);
+			if (!(init_phys & 0x01)) {
+				init_phys >>= 0x01;
+				continue;
+			}
+
+			memset(p, 0, sizeof(*p));
+
+			/* Set window to be the same value as the interval to
+			 * enable continuous scanning.
+			 */
+
+			min_interval = conn->le_conn_min_interval;
+			max_interval = conn->le_conn_max_interval;
+			supv_timeout = conn->le_supv_timeout;
+
+			p->scan_interval = cpu_to_le16(hdev->le_scan_interval);
+			p->scan_window = p->scan_interval;
+			p->conn_interval_min = cpu_to_le16(min_interval);
+			p->conn_interval_max = cpu_to_le16(max_interval);
+			p->conn_latency = cpu_to_le16(conn->le_conn_latency);
+			p->supervision_timeout = cpu_to_le16(supv_timeout);
+			p->min_ce_len = cpu_to_le16(0x0000);
+			p->max_ce_len = cpu_to_le16(0x0000);
+
+			p++;
+			plen += sizeof(*p);
+			init_phys >>= 1;
+		}
 
-		hci_req_add(req, HCI_OP_LE_EXT_CREATE_CONN, sizeof(data), data);
+		hci_req_add(req, HCI_OP_LE_EXT_CREATE_CONN, plen, data);
 
 	} else {
 		struct hci_cp_le_create_conn cp;
-- 
2.7.4

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

* [PATCH v4 07/13] Bluetooth: Read no of adv sets during init
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (5 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 06/13] Bluetooth: Use selected PHYs in extended connect Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 17:32   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 08/13] Bluetooth: Impmlement extended adv enable Jaganath Kanakkassery
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This patch reads the number of advertising sets in the controller
during init and save it in hdev.

This also checks ext adv support before send Read Adv TX Power
since legacy and extended Adv commands should not be mixed.

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h      |  7 +++++++
 include/net/bluetooth/hci_core.h |  4 ++++
 net/bluetooth/hci_core.c         | 12 ++++++++++--
 net/bluetooth/hci_event.c        | 18 ++++++++++++++++++
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fcd1d57..e584863 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -411,6 +411,7 @@ enum {
 #define HCI_LE_SLAVE_FEATURES		0x08
 #define HCI_LE_PING			0x10
 #define HCI_LE_DATA_LEN_EXT		0x20
+#define HCI_LE_EXT_ADV			0x10
 #define HCI_LE_EXT_SCAN_POLICY		0x80
 #define HCI_LE_PHY_2M			0x01
 #define HCI_LE_PHY_CODED		0x08
@@ -1580,6 +1581,12 @@ struct hci_cp_le_ext_conn_param {
 	__le16 max_ce_len;
 } __packed;
 
+#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS	0x203b
+struct hci_rp_le_read_num_supported_adv_sets {
+	__u8  status;
+	__u8  num_of_sets;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 33aab89e..e845ca6 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -222,6 +222,7 @@ struct hci_dev {
 	__u8		le_features[8];
 	__u8		le_white_list_size;
 	__u8		le_resolv_list_size;
+	__u8		le_no_of_adv_sets;
 	__u8		le_states[8];
 	__u8		commands[64];
 	__u8		hci_ver;
@@ -1180,6 +1181,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 /* Use ext create connection if command is supported */
 #define use_ext_conn(dev) ((dev)->commands[37] & 0x80)
 
+/* Extended advertising support */
+#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
+
 /* ----- HCI protocols ----- */
 #define HCI_PROTO_DEFER             0x01
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0d88dc9..b423587 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -715,8 +715,10 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
 		hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
 			    events);
 
-		if (hdev->commands[25] & 0x40) {
-			/* Read LE Advertising Channel TX Power */
+		if ((hdev->commands[25] & 0x40) && !ext_adv_capable(hdev)) {
+			/* Read LE Advertising Channel TX Power only if
+			 * extended advertising is not supported
+			 */
 			hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
 		}
 
@@ -750,6 +752,12 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
 			hci_req_add(req, HCI_OP_LE_READ_DEF_DATA_LEN, 0, NULL);
 		}
 
+		if (ext_adv_capable(hdev)) {
+			/* Read LE Number of Supported Advertising Sets */
+			hci_req_add(req, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS,
+				    0, NULL);
+		}
+
 		hci_set_le_support(req);
 	}
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 027abe6..90e7235 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1267,6 +1267,20 @@ static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
 	le_set_scan_enable_complete(hdev, cp->enable);
 }
 
+static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev,
+				      struct sk_buff *skb)
+{
+	struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status,
+	       rp->num_of_sets);
+
+	if (rp->status)
+		return;
+
+	hdev->le_no_of_adv_sets = rp->num_of_sets;
+}
+
 static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
@@ -3189,6 +3203,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
 		hci_cc_le_set_default_phy(hdev, skb);
 		break;
 
+	case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS:
+		hci_cc_le_read_num_adv_sets(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
 		break;
-- 
2.7.4

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

* [PATCH v4 08/13] Bluetooth: Impmlement extended adv enable
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (6 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 07/13] Bluetooth: Read no of adv sets during init Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 18:38   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 09/13] Bluetooth: Use Set ext adv/scan rsp data if controller supports Jaganath Kanakkassery
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This patch basically replaces legacy adv with extended adv
based on the controller support. Currently there is no
design change. ie only one adv set will be enabled at a time.

< HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25
        Handle: 0x00
        Properties: 0x0010
          Use legacy advertising PDUs: ADV_NONCONN_IND
        Min advertising interval: 1280.000 msec (0x0800)
        Max advertising interval: 1280.000 msec (0x0800)
        Channel map: 37, 38, 39 (0x07)
        Own address type: Random (0x01)
        Peer address type: Public (0x00)
        Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
        Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
        TX power: 127 dbm (0x7f)
        Primary PHY: LE 1M (0x01)
        Secondary max skip: 0x00
        Secondary PHY: LE 1M (0x01)
        SID: 0x00
        Scan request notifications: Disabled (0x00)
> HCI Event: Command Complete (0x0e) plen 5
      LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1
        Status: Success (0x00)
        TX power (selected): 7 dbm (0x07)
< HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6
        Extended advertising: Enabled (0x01)
        Number of sets: 1 (0x01)
        Entry 0
          Handle: 0x00
          Duration: 0 ms (0x00)
          Max ext adv events: 0
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
        Status: Success (0x00)

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h |  39 ++++++++++++
 net/bluetooth/hci_event.c   |  63 +++++++++++++++++++
 net/bluetooth/hci_request.c | 144 ++++++++++++++++++++++++++++++++++++++++----
 net/bluetooth/hci_request.h |   3 +
 net/bluetooth/mgmt.c        |  19 ++++--
 5 files changed, 251 insertions(+), 17 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index e584863..c0c542d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1587,6 +1587,45 @@ struct hci_rp_le_read_num_supported_adv_sets {
 	__u8  num_of_sets;
 } __packed;
 
+#define HCI_OP_LE_SET_EXT_ADV_PARAMS			0x2036
+struct hci_cp_le_set_ext_adv_params {
+	__u8  handle;
+	__le16 evt_properties;
+	__u8  min_interval[3];
+	__u8  max_interval[3];
+	__u8  channel_map;
+	__u8  own_addr_type;
+	__u8  peer_addr_type;
+	bdaddr_t  peer_addr;
+	__u8  filter_policy;
+	__u8  tx_power;
+	__u8  primary_phy;
+	__u8  secondary_max_skip;
+	__u8  secondary_phy;
+	__u8  sid;
+	__u8  notif_enable;
+} __packed;
+
+#define HCI_ADV_PHY_1M		0X01
+
+struct hci_rp_le_set_ext_adv_params {
+	__u8  status;
+	__u8  tx_power;
+} __attribute__ ((packed));
+
+#define HCI_OP_LE_SET_EXT_ADV_ENABLE			0x2039
+struct hci_cp_le_set_ext_adv_enable {
+	__u8  enable;
+	__u8  num_of_sets;
+	__u8  data[0];
+} __packed;
+
+struct hci_cp_ext_adv_set {
+	__u8  handle;
+	__le16 duration;
+	__u8  max_events;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 90e7235..e17002f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1099,6 +1099,41 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
+					 struct sk_buff *skb)
+{
+	struct hci_cp_le_set_ext_adv_enable *cp;
+	struct hci_cp_ext_adv_set *adv_set;
+	__u8 status = *((__u8 *) skb->data);
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	if (status)
+		return;
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
+	if (!cp)
+		return;
+
+	adv_set = (void *) cp->data;
+
+	hci_dev_lock(hdev);
+
+	if (cp->enable) {
+		struct hci_conn *conn;
+
+		hci_dev_set_flag(hdev, HCI_LE_ADV);
+
+		conn = hci_lookup_le_connect(hdev);
+		if (conn)
+			queue_delayed_work(hdev->workqueue,
+					   &conn->le_conn_timeout,
+					   conn->conn_timeout);
+	}
+
+	hci_dev_unlock(hdev);
+}
+
 static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_cp_le_set_scan_param *cp;
@@ -1486,6 +1521,26 @@ static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data;
+	struct hci_cp_le_set_ext_adv_params *cp;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
+	if (!cp)
+		return;
+
+	hci_dev_lock(hdev);
+	hdev->adv_addr_type = cp->own_addr_type;
+	hdev->adv_tx_power = rp->tx_power;
+	hci_dev_unlock(hdev);
+}
+
 static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_rp_read_rssi *rp = (void *) skb->data;
@@ -3207,6 +3262,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
 		hci_cc_le_read_num_adv_sets(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_EXT_ADV_PARAMS:
+		hci_cc_set_ext_adv_param(hdev, skb);
+		break;
+
+	case HCI_OP_LE_SET_EXT_ADV_ENABLE:
+		hci_cc_le_set_ext_adv_enable(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
 		break;
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 7f5950e..a2091b5 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -894,6 +894,24 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
 			   hdev->le_scan_window, own_addr_type, filter_policy);
 }
 
+static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
+{
+	struct adv_info *adv_instance;
+
+	/* Ignore instance 0 */
+	if (instance == 0x00)
+		return 0;
+
+	adv_instance = hci_find_adv_instance(hdev, instance);
+	if (!adv_instance)
+		return 0;
+
+	/* TODO: Take into account the "appearance" and "local-name" flags here.
+	 * These are currently being ignored as they are not supported.
+	 */
+	return adv_instance->scan_rsp_len;
+}
+
 static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
 {
 	u8 instance = hdev->cur_adv_instance;
@@ -1303,9 +1321,13 @@ void hci_req_reenable_advertising(struct hci_dev *hdev)
 		__hci_req_schedule_adv_instance(&req, hdev->cur_adv_instance,
 						true);
 	} else {
-		__hci_req_update_adv_data(&req, 0x00);
-		__hci_req_update_scan_rsp_data(&req, 0x00);
-		__hci_req_enable_advertising(&req);
+		if (ext_adv_capable(hdev)) {
+			__hci_req_start_ext_adv(&req, 0x00);
+		} else {
+			__hci_req_update_adv_data(&req, 0x00);
+			__hci_req_update_scan_rsp_data(&req, 0x00);
+			__hci_req_enable_advertising(&req);
+		}
 	}
 
 	hci_req_run(&req, adv_enable_complete);
@@ -1342,6 +1364,88 @@ static void adv_timeout_expire(struct work_struct *work)
 	hci_dev_unlock(hdev);
 }
 
+static int __hci_req_setup_ext_adv_instance(struct hci_request *req,
+					    u8 instance)
+{
+	struct hci_cp_le_set_ext_adv_params cp;
+	struct hci_dev *hdev = req->hdev;
+	bool connectable;
+	u32 flags;
+	/* In ext adv set param interval is 3 octets */
+	const u8 adv_interval[3] = { 0x00, 0x08, 0x00 };
+
+	flags = get_adv_instance_flags(hdev, instance);
+
+	/* If the "connectable" instance flag was not set, then choose between
+	 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
+	 */
+	connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
+		      mgmt_get_connectable(hdev);
+
+	 if (!is_advertising_allowed(hdev, connectable))
+		return -EPERM;
+
+	memset(&cp, 0, sizeof(cp));
+
+	memcpy(cp.min_interval, adv_interval, sizeof(cp.min_interval));
+	memcpy(cp.max_interval, adv_interval, sizeof(cp.max_interval));
+
+	if (connectable)
+		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);
+	else if (get_adv_instance_scan_rsp_len(hdev, instance))
+		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);
+	else
+		cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);
+
+	cp.own_addr_type = BDADDR_LE_PUBLIC;
+	cp.channel_map = hdev->le_adv_channel_map;
+	cp.tx_power = 127;
+	cp.primary_phy = HCI_ADV_PHY_1M;
+	cp.secondary_phy = HCI_ADV_PHY_1M;
+	cp.handle = 0;
+
+	hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
+
+	return 0;
+}
+
+void __hci_req_enable_ext_advertising(struct hci_request *req)
+{
+	struct hci_cp_le_set_ext_adv_enable *cp;
+	struct hci_cp_ext_adv_set *adv_set;
+	u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
+
+	cp = (void *) data;
+	adv_set = (void *) cp->data;
+
+	memset(cp, 0, sizeof(*cp));
+
+	cp->enable = 0x01;
+	cp->num_of_sets = 0x01;
+
+	memset(adv_set, 0, sizeof(*adv_set));
+
+	adv_set->handle = 0;
+
+	hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE,
+		    sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
+		    data);
+}
+
+int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
+{
+	struct hci_dev *hdev = req->hdev;
+	int err;
+
+	err = __hci_req_setup_ext_adv_instance(req, instance);
+	if (err < 0)
+		return err;
+
+	__hci_req_enable_ext_advertising(req);
+
+	return 0;
+}
+
 int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
 				    bool force)
 {
@@ -1395,9 +1499,13 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
 		return 0;
 
 	hdev->cur_adv_instance = instance;
-	__hci_req_update_adv_data(req, instance);
-	__hci_req_update_scan_rsp_data(req, instance);
-	__hci_req_enable_advertising(req);
+	if (ext_adv_capable(hdev)) {
+		__hci_req_start_ext_adv(req, instance);
+	} else {
+		__hci_req_update_adv_data(req, instance);
+		__hci_req_update_scan_rsp_data(req, instance);
+		__hci_req_enable_advertising(req);
+	}
 
 	return 0;
 }
@@ -1668,8 +1776,12 @@ static int connectable_update(struct hci_request *req, unsigned long opt)
 
 	/* Update the advertising parameters if necessary */
 	if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
-	    !list_empty(&hdev->adv_instances))
-		__hci_req_enable_advertising(req);
+	    !list_empty(&hdev->adv_instances)) {
+		if (ext_adv_capable(hdev))
+			__hci_req_start_ext_adv(req, hdev->cur_adv_instance);
+		else
+			__hci_req_enable_advertising(req);
+	}
 
 	__hci_update_background_scan(req);
 
@@ -1778,8 +1890,12 @@ static int discoverable_update(struct hci_request *req, unsigned long opt)
 		/* Discoverable mode affects the local advertising
 		 * address in limited privacy mode.
 		 */
-		if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY))
-			__hci_req_enable_advertising(req);
+		if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) {
+			if (ext_adv_capable(hdev))
+				__hci_req_start_ext_adv(req, 0x00);
+			else
+				__hci_req_enable_advertising(req);
+		}
 	}
 
 	hci_dev_unlock(hdev);
@@ -2375,8 +2491,12 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
 			__hci_req_update_adv_data(req, 0x00);
 			__hci_req_update_scan_rsp_data(req, 0x00);
 
-			if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
-				__hci_req_enable_advertising(req);
+			if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
+				if (ext_adv_capable(hdev))
+					__hci_req_start_ext_adv(req, 0x00);
+				else
+					__hci_req_enable_advertising(req);
+			}
 		} else if (!list_empty(&hdev->adv_instances)) {
 			struct adv_info *adv_instance;
 
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index 702beb1..9b8c74d 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -80,6 +80,9 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
 				struct hci_request *req, u8 instance,
 				bool force);
 
+int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
+void __hci_req_enable_ext_advertising(struct hci_request *req);
+
 void __hci_req_update_class(struct hci_request *req);
 
 /* Returns true if HCI commands were queued */
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1c2ed42..22997f8 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -961,7 +961,10 @@ static void rpa_expired(struct work_struct *work)
 	 * function.
 	 */
 	hci_req_init(&req, hdev);
-	__hci_req_enable_advertising(&req);
+	if (ext_adv_capable(hdev))
+		__hci_req_start_ext_adv(&req, hdev->cur_adv_instance);
+	else
+		__hci_req_enable_advertising(&req);
 	hci_req_run(&req, NULL);
 }
 
@@ -4405,9 +4408,14 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
 		 * HCI_ADVERTISING flag is not yet set.
 		 */
 		hdev->cur_adv_instance = 0x00;
-		__hci_req_update_adv_data(&req, 0x00);
-		__hci_req_update_scan_rsp_data(&req, 0x00);
-		__hci_req_enable_advertising(&req);
+
+		if (ext_adv_capable(hdev)) {
+			__hci_req_start_ext_adv(&req, 0x00);
+		} else {
+			__hci_req_update_adv_data(&req, 0x00);
+			__hci_req_update_scan_rsp_data(&req, 0x00);
+			__hci_req_enable_advertising(&req);
+		}
 	} else {
 		__hci_req_disable_advertising(&req);
 	}
@@ -6335,7 +6343,8 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
 	flags |= MGMT_ADV_FLAG_APPEARANCE;
 	flags |= MGMT_ADV_FLAG_LOCAL_NAME;
 
-	if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
+	if ((hdev->adv_tx_power != HCI_TX_POWER_INVALID) ||
+	    ext_adv_capable(hdev))
 		flags |= MGMT_ADV_FLAG_TX_POWER;
 
 	return flags;
-- 
2.7.4

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

* [PATCH v4 09/13] Bluetooth: Use Set ext adv/scan rsp data if controller supports
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (7 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 08/13] Bluetooth: Impmlement extended adv enable Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 18:47   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 10/13] Bluetooth: Implement disable and removal of adv instance Jaganath Kanakkassery
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This patch implements Set Ext Adv data and Set Ext Scan rsp data
if controller support extended advertising.

Currently the operation is set as Complete data and fragment
preference is set as no fragment

< HCI Command: LE Set Extended Advertising Data (0x08|0x0037) plen 35
        Handle: 0x00
        Operation: Complete extended advertising data (0x03)
        Fragment preference: Minimize fragmentation (0x01)
        Data length: 0x15
        16-bit Service UUIDs (complete): 2 entries
          Heart Rate (0x180d)
          Battery Service (0x180f)
        Name (complete): Test LE
        Company: Google (224)
          Data: 0102
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Advertising Data (0x08|0x0037) ncmd 1
        Status: Success (0x00)

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h |  22 ++++++++
 net/bluetooth/hci_request.c | 124 +++++++++++++++++++++++++++++++++-----------
 net/bluetooth/hci_request.h |   1 +
 net/bluetooth/mgmt.c        |  10 +++-
 4 files changed, 124 insertions(+), 33 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index c0c542d..5b84d9a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1626,6 +1626,28 @@ struct hci_cp_ext_adv_set {
 	__u8  max_events;
 } __packed;
 
+#define HCI_OP_LE_SET_EXT_ADV_DATA		0x2037
+struct hci_cp_le_set_ext_adv_data {
+	__u8  handle;
+	__u8  operation;
+	__u8  fragment_preference;
+	__u8  length;
+	__u8  data[HCI_MAX_AD_LENGTH];
+} __packed;
+
+#define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA		0x2038
+struct hci_cp_le_set_ext_scan_rsp_data {
+	__u8  handle;
+	__u8  operation;
+	__u8  fragment_preference;
+	__u8  length;
+	__u8  data[HCI_MAX_AD_LENGTH];
+} __packed;
+
+#define LE_SET_ADV_DATA_OP_COMPLETE	0x03
+
+#define LE_SET_ADV_DATA_NO_FRAG		0x01
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index a2091b5..5fde161 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1173,29 +1173,58 @@ static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
 void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
 {
 	struct hci_dev *hdev = req->hdev;
-	struct hci_cp_le_set_scan_rsp_data cp;
 	u8 len;
 
 	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
 		return;
 
-	memset(&cp, 0, sizeof(cp));
+	if (ext_adv_capable(hdev)) {
+		struct hci_cp_le_set_ext_scan_rsp_data cp;
 
-	if (instance)
-		len = create_instance_scan_rsp_data(hdev, instance, cp.data);
-	else
-		len = create_default_scan_rsp_data(hdev, cp.data);
+		memset(&cp, 0, sizeof(cp));
 
-	if (hdev->scan_rsp_data_len == len &&
-	    !memcmp(cp.data, hdev->scan_rsp_data, len))
-		return;
+		if (instance)
+			len = create_instance_scan_rsp_data(hdev, instance,
+							    cp.data);
+		else
+			len = create_default_scan_rsp_data(hdev, cp.data);
+
+		if (hdev->scan_rsp_data_len == len &&
+		    !memcmp(cp.data, hdev->scan_rsp_data, len))
+			return;
+
+		memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
+		hdev->scan_rsp_data_len = len;
+
+		cp.handle = 0;
+		cp.length = len;
+		cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
+		cp.fragment_preference = LE_SET_ADV_DATA_NO_FRAG;
 
-	memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
-	hdev->scan_rsp_data_len = len;
+		hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, sizeof(cp),
+			    &cp);
+	} else {
+		struct hci_cp_le_set_scan_rsp_data cp;
+
+		memset(&cp, 0, sizeof(cp));
+
+		if (instance)
+			len = create_instance_scan_rsp_data(hdev, instance,
+							    cp.data);
+		else
+			len = create_default_scan_rsp_data(hdev, cp.data);
+
+		if (hdev->scan_rsp_data_len == len &&
+		    !memcmp(cp.data, hdev->scan_rsp_data, len))
+			return;
 
-	cp.length = len;
+		memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
+		hdev->scan_rsp_data_len = len;
 
-	hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
+		cp.length = len;
+
+		hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
+	}
 }
 
 static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
@@ -1269,27 +1298,51 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
 void __hci_req_update_adv_data(struct hci_request *req, u8 instance)
 {
 	struct hci_dev *hdev = req->hdev;
-	struct hci_cp_le_set_adv_data cp;
 	u8 len;
 
 	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
 		return;
 
-	memset(&cp, 0, sizeof(cp));
+	if (ext_adv_capable(hdev)) {
+		struct hci_cp_le_set_ext_adv_data cp;
 
-	len = create_instance_adv_data(hdev, instance, cp.data);
+		memset(&cp, 0, sizeof(cp));
 
-	/* There's nothing to do if the data hasn't changed */
-	if (hdev->adv_data_len == len &&
-	    memcmp(cp.data, hdev->adv_data, len) == 0)
-		return;
+		len = create_instance_adv_data(hdev, instance, cp.data);
+
+		/* There's nothing to do if the data hasn't changed */
+		if (hdev->adv_data_len == len &&
+		    memcmp(cp.data, hdev->adv_data, len) == 0)
+			return;
+
+		memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
+		hdev->adv_data_len = len;
+
+		cp.length = len;
+		cp.handle = 0;
+		cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
+		cp.fragment_preference = LE_SET_ADV_DATA_NO_FRAG;
+
+		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(cp), &cp);
+	} else {
+		struct hci_cp_le_set_adv_data cp;
 
-	memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
-	hdev->adv_data_len = len;
+		memset(&cp, 0, sizeof(cp));
+
+		len = create_instance_adv_data(hdev, instance, cp.data);
+
+		/* There's nothing to do if the data hasn't changed */
+		if (hdev->adv_data_len == len &&
+		    memcmp(cp.data, hdev->adv_data, len) == 0)
+			return;
+
+		memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
+		hdev->adv_data_len = len;
 
-	cp.length = len;
+		cp.length = len;
 
-	hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
+		hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
+	}
 }
 
 int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance)
@@ -1364,8 +1417,7 @@ static void adv_timeout_expire(struct work_struct *work)
 	hci_dev_unlock(hdev);
 }
 
-static int __hci_req_setup_ext_adv_instance(struct hci_request *req,
-					    u8 instance)
+int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 {
 	struct hci_cp_le_set_ext_adv_params cp;
 	struct hci_dev *hdev = req->hdev;
@@ -1441,6 +1493,8 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
 	if (err < 0)
 		return err;
 
+	__hci_req_update_adv_data(req, instance);
+	__hci_req_update_scan_rsp_data(req, instance);
 	__hci_req_enable_ext_advertising(req);
 
 	return 0;
@@ -2488,14 +2542,22 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
 		 */
 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
 		    list_empty(&hdev->adv_instances)) {
-			__hci_req_update_adv_data(req, 0x00);
-			__hci_req_update_scan_rsp_data(req, 0x00);
+			int err = 0;
+
+			if (ext_adv_capable(hdev))
+				err = __hci_req_setup_ext_adv_instance(req,
+								       0x00);
+
+			if (!err) {
+				__hci_req_update_adv_data(req, 0x00);
+				__hci_req_update_scan_rsp_data(req, 0x00);
+			}
 
 			if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
-				if (ext_adv_capable(hdev))
-					__hci_req_start_ext_adv(req, 0x00);
-				else
+				if (!ext_adv_capable(hdev))
 					__hci_req_enable_advertising(req);
+				else if (!err)
+					__hci_req_enable_ext_advertising(req);
 			}
 		} else if (!list_empty(&hdev->adv_instances)) {
 			struct adv_info *adv_instance;
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index 9b8c74d..6afc624 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -80,6 +80,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
 				struct hci_request *req, u8 instance,
 				bool force);
 
+int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
 int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
 void __hci_req_enable_ext_advertising(struct hci_request *req);
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 22997f8..ed7f35d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1868,10 +1868,16 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
 	 */
 	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
 		struct hci_request req;
+		int err = 0;
 
 		hci_req_init(&req, hdev);
-		__hci_req_update_adv_data(&req, 0x00);
-		__hci_req_update_scan_rsp_data(&req, 0x00);
+		if (ext_adv_capable(hdev))
+			err = __hci_req_setup_ext_adv_instance(&req, 0x00);
+
+		if (!err) {
+			__hci_req_update_adv_data(&req, 0x00);
+			__hci_req_update_scan_rsp_data(&req, 0x00);
+		}
 		hci_req_run(&req, NULL);
 		hci_update_background_scan(hdev);
 	}
-- 
2.7.4

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

* [PATCH v4 10/13] Bluetooth: Implement disable and removal of adv instance
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (8 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 09/13] Bluetooth: Use Set ext adv/scan rsp data if controller supports Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 18:50   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 11/13] Bluetooth: Use ext adv for directed adv Jaganath Kanakkassery
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

If ext adv is enabled then use ext adv to disable as well.
Also remove the adv set during LE disable.

< HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 2
        Extended advertising: Disabled (0x00)
        Number of sets: Disable all sets (0x00)
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
        Status: Success (0x00)

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h |  7 +++++++
 net/bluetooth/hci_event.c   |  2 ++
 net/bluetooth/hci_request.c | 22 ++++++++++++++++++++--
 net/bluetooth/hci_request.h |  1 +
 net/bluetooth/mgmt.c        |  3 +++
 5 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 5b84d9a..1a68530 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1648,6 +1648,13 @@ struct hci_cp_le_set_ext_scan_rsp_data {
 
 #define LE_SET_ADV_DATA_NO_FRAG		0x01
 
+#define HCI_OP_LE_REMOVE_ADV_SET	0x203c
+struct hci_cp_le_remove_adv_set {
+	__u8  handle;
+} __packed;
+
+#define HCI_OP_LE_CLEAR_ADV_SETS	0x203d
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index e17002f..e703880 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1129,6 +1129,8 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
 			queue_delayed_work(hdev->workqueue,
 					   &conn->le_conn_timeout,
 					   conn->conn_timeout);
+	} else {
+		hci_dev_clear_flag(hdev, HCI_LE_ADV);
 	}
 
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 5fde161..7051c5b 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -933,9 +933,19 @@ static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
 
 void __hci_req_disable_advertising(struct hci_request *req)
 {
-	u8 enable = 0x00;
+	if (ext_adv_capable(req->hdev)) {
+		struct hci_cp_le_set_ext_adv_enable cp;
 
-	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+		cp.enable = 0x00;
+		/* Disable all adv sets */
+		cp.num_of_sets = 0x00;
+
+		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(cp), &cp);
+	} else {
+		u8 enable = 0x00;
+
+		hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+	}
 }
 
 static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
@@ -1417,6 +1427,11 @@ static void adv_timeout_expire(struct work_struct *work)
 	hci_dev_unlock(hdev);
 }
 
+void __hci_req_clear_ext_adv_sets(struct hci_request *req)
+{
+	hci_req_add(req, HCI_OP_LE_REMOVE_ADV_SET, 0, NULL);
+}
+
 int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 {
 	struct hci_cp_le_set_ext_adv_params cp;
@@ -1489,6 +1504,9 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
 	struct hci_dev *hdev = req->hdev;
 	int err;
 
+	if (hci_dev_test_flag(hdev, HCI_LE_ADV))
+		__hci_req_disable_advertising(req);
+
 	err = __hci_req_setup_ext_adv_instance(req, instance);
 	if (err < 0)
 		return err;
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index 6afc624..2451861 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -83,6 +83,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
 int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
 int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
 void __hci_req_enable_ext_advertising(struct hci_request *req);
+void __hci_req_clear_ext_adv_sets(struct hci_request *req);
 
 void __hci_req_update_class(struct hci_request *req);
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ed7f35d..4bc79ab 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1976,6 +1976,9 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 	} else {
 		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
 			__hci_req_disable_advertising(&req);
+
+		if (ext_adv_capable(hdev))
+			__hci_req_clear_ext_adv_sets(&req);
 	}
 
 	hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
-- 
2.7.4

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

* [PATCH v4 11/13] Bluetooth: Use ext adv for directed adv
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (9 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 10/13] Bluetooth: Implement disable and removal of adv instance Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 18:56   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 12/13] Bluetooth: Implement Set ADV set random address Jaganath Kanakkassery
  2018-07-11  9:31 ` [PATCH v4 13/13] Bluetooth: Implement secondary advertising on different PHYs Jaganath Kanakkassery
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This patch does extended advertising for directed advertising
if the controller supportes. Instance 0 is used for directed
advertising.

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 net/bluetooth/hci_conn.c | 67 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 45 insertions(+), 22 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5d421a2..fc27bd8 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -870,35 +870,58 @@ static void hci_req_directed_advertising(struct hci_request *req,
 					 struct hci_conn *conn)
 {
 	struct hci_dev *hdev = req->hdev;
-	struct hci_cp_le_set_adv_param cp;
 	u8 own_addr_type;
 	u8 enable;
 
-	/* Clear the HCI_LE_ADV bit temporarily so that the
-	 * hci_update_random_address knows that it's safe to go ahead
-	 * and write a new random address. The flag will be set back on
-	 * as soon as the SET_ADV_ENABLE HCI command completes.
-	 */
-	hci_dev_clear_flag(hdev, HCI_LE_ADV);
+	if (ext_adv_capable(hdev)) {
+		struct hci_cp_le_set_ext_adv_params cp;
 
-	/* Set require_privacy to false so that the remote device has a
-	 * chance of identifying us.
-	 */
-	if (hci_update_random_address(req, false, conn_use_rpa(conn),
-				      &own_addr_type) < 0)
-		return;
+		memset(&cp, 0, sizeof(cp));
 
-	memset(&cp, 0, sizeof(cp));
-	cp.type = LE_ADV_DIRECT_IND;
-	cp.own_address_type = own_addr_type;
-	cp.direct_addr_type = conn->dst_type;
-	bacpy(&cp.direct_addr, &conn->dst);
-	cp.channel_map = hdev->le_adv_channel_map;
+		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_DIRECT_IND);
+		cp.own_addr_type = own_addr_type;
+		cp.channel_map = hdev->le_adv_channel_map;
+		cp.tx_power = 127;
+		cp.primary_phy = HCI_ADV_PHY_1M;
+		cp.secondary_phy = HCI_ADV_PHY_1M;
+		cp.handle = 0; /* Use instance 0 for directed adv */
+		cp.own_addr_type = own_addr_type;
+		cp.peer_addr_type = conn->dst_type;
+		bacpy(&cp.peer_addr, &conn->dst);
+
+		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
 
-	hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
+		__hci_req_enable_ext_advertising(req);
+	} else {
+		struct hci_cp_le_set_adv_param cp;
+
+		/* Clear the HCI_LE_ADV bit temporarily so that the
+		 * hci_update_random_address knows that it's safe to go ahead
+		 * and write a new random address. The flag will be set back on
+		 * as soon as the SET_ADV_ENABLE HCI command completes.
+		 */
+		hci_dev_clear_flag(hdev, HCI_LE_ADV);
 
-	enable = 0x01;
-	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+		/* Set require_privacy to false so that the remote device has a
+		 * chance of identifying us.
+		 */
+		if (hci_update_random_address(req, false, conn_use_rpa(conn),
+					      &own_addr_type) < 0)
+			return;
+
+		memset(&cp, 0, sizeof(cp));
+		cp.type = LE_ADV_DIRECT_IND;
+		cp.own_address_type = own_addr_type;
+		cp.direct_addr_type = conn->dst_type;
+		bacpy(&cp.direct_addr, &conn->dst);
+		cp.channel_map = hdev->le_adv_channel_map;
+
+		hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
+
+		enable = 0x01;
+		hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
+			    &enable);
+	}
 
 	conn->state = BT_CONNECT;
 }
-- 
2.7.4

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

* [PATCH v4 12/13] Bluetooth: Implement Set ADV set random address
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (10 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 11/13] Bluetooth: Use ext adv for directed adv Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  2018-07-14 20:52   ` Marcel Holtmann
  2018-07-11  9:31 ` [PATCH v4 13/13] Bluetooth: Implement secondary advertising on different PHYs Jaganath Kanakkassery
  12 siblings, 1 reply; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This basically sets the random address for the instance 0.
Random address can be set only if the instance is created which
is done in Set ext adv param.

This introduces a hci_get_random_address() which returns the
own address type and random address (rpa, nrpa or static) based
on the instance flags and hdev flags. New function is required
since own address type should be known before setting adv params
but address can be set only after setting params.

< HCI Command: LE Set Advertising Set Random Address (0x08|0x0035) plen 7
        Advertising handle: 0x00
        Advertising random address: 3C:8E:56:9B:77:84 (OUI 3C-8E-56)
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Advertising Set Random Address (0x08|0x0035) ncmd 1
        Status: Success (0x00)

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h |   6 +++
 net/bluetooth/hci_conn.c    |  23 +++++++++
 net/bluetooth/hci_event.c   |  24 ++++++++++
 net/bluetooth/hci_request.c | 111 +++++++++++++++++++++++++++++++++++++++++++-
 net/bluetooth/hci_request.h |   3 ++
 5 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 1a68530..40a532a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1655,6 +1655,12 @@ struct hci_cp_le_remove_adv_set {
 
 #define HCI_OP_LE_CLEAR_ADV_SETS	0x203d
 
+#define HCI_OP_LE_SET_ADV_SET_RAND_ADDR	0x2035
+struct hci_cp_le_set_adv_set_rand_addr {
+	__u8  handle;
+	bdaddr_t  bdaddr;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index fc27bd8..cf180b24 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -875,6 +875,14 @@ static void hci_req_directed_advertising(struct hci_request *req,
 
 	if (ext_adv_capable(hdev)) {
 		struct hci_cp_le_set_ext_adv_params cp;
+		bdaddr_t random_addr;
+
+		/* Set require_privacy to false so that the remote device has a
+		 * chance of identifying us.
+		 */
+		if (hci_get_random_address(hdev, false, conn_use_rpa(conn),
+					   &own_addr_type, &random_addr) < 0)
+			return;
 
 		memset(&cp, 0, sizeof(cp));
 
@@ -891,6 +899,21 @@ static void hci_req_directed_advertising(struct hci_request *req,
 
 		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
 
+		if (own_addr_type == ADDR_LE_DEV_RANDOM &&
+		    bacmp(&random_addr, BDADDR_ANY) &&
+		    bacmp(&random_addr, &hdev->random_addr)) {
+			struct hci_cp_le_set_adv_set_rand_addr cp;
+
+			memset(&cp, 0, sizeof(cp));
+
+			cp.handle = 0;
+			bacpy(&cp.bdaddr, &random_addr);
+
+			hci_req_add(req,
+				    HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
+				    sizeof(cp), &cp);
+		}
+
 		__hci_req_enable_ext_advertising(req);
 	} else {
 		struct hci_cp_le_set_adv_param cp;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index e703880..dfb2a82 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1061,6 +1061,26 @@ static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
 	hdev->le_tx_def_phys = cp->tx_phys;
 	hdev->le_rx_def_phys = cp->rx_phys;
 
+        hci_dev_unlock(hdev);
+}
+
+static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
+                                              struct sk_buff *skb)
+{
+        __u8 status = *((__u8 *) skb->data);
+        struct hci_cp_le_set_adv_set_rand_addr *cp;
+
+	if (status)
+		return;
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
+	if (!cp)
+		return;
+
+	hci_dev_lock(hdev);
+
+	bacpy(&hdev->random_addr, &cp->bdaddr);
+
 	hci_dev_unlock(hdev);
 }
 
@@ -3272,6 +3292,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
 		hci_cc_le_set_ext_adv_enable(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_ADV_SET_RAND_ADDR:
+		hci_cc_le_set_adv_set_random_addr(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
 		break;
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 7051c5b..6825a65 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1427,6 +1427,87 @@ static void adv_timeout_expire(struct work_struct *work)
 	hci_dev_unlock(hdev);
 }
 
+int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
+			   bool use_rpa, u8 *own_addr_type, bdaddr_t *rand_addr)
+{
+	int err;
+
+	bacpy(rand_addr, BDADDR_ANY);
+
+	/* If privacy is enabled use a resolvable private address. If
+	 * current RPA has expired then generate a new one.
+	 */
+	if (use_rpa) {
+		*own_addr_type = ADDR_LE_DEV_RANDOM;
+
+		if (!hci_dev_test_and_clear_flag(hdev, HCI_RPA_EXPIRED) &&
+		    !bacmp(&hdev->random_addr, &hdev->rpa))
+			return 0;
+
+		err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
+		if (err < 0) {
+			BT_ERR("%s failed to generate new RPA", hdev->name);
+			return err;
+		}
+
+		bacpy(rand_addr, &hdev->rpa);
+
+		return 0;
+	}
+
+	/* In case of required privacy without resolvable private address,
+	 * use an non-resolvable private address. This is useful for active
+	 * scanning and non-connectable advertising.
+	 */
+	if (require_privacy) {
+		bdaddr_t nrpa;
+
+		while (true) {
+			/* The non-resolvable private address is generated
+			 * from random six bytes with the two most significant
+			 * bits cleared.
+			 */
+			get_random_bytes(&nrpa, 6);
+			nrpa.b[5] &= 0x3f;
+
+			/* The non-resolvable private address shall not be
+			 * equal to the public address.
+			 */
+			if (bacmp(&hdev->bdaddr, &nrpa))
+				break;
+		}
+
+		*own_addr_type = ADDR_LE_DEV_RANDOM;
+		bacpy(rand_addr, &nrpa);
+
+		return 0;
+	}
+
+	/* If forcing static address is in use or there is no public
+	 * address use the static address as random address
+	 *
+	 * In case BR/EDR has been disabled on a dual-mode controller
+	 * and a static address has been configured, then use that
+	 * address instead of the public BR/EDR address.
+	 */
+	if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
+	    !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
+	    (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
+	     bacmp(&hdev->static_addr, BDADDR_ANY))) {
+		*own_addr_type = ADDR_LE_DEV_RANDOM;
+		bacpy(rand_addr, &hdev->static_addr);
+
+		return 0;
+	}
+
+	/* Neither privacy nor static address is being used so use a
+	 * public address.
+	 */
+	*own_addr_type = ADDR_LE_DEV_PUBLIC;
+
+	return 0;
+}
+
 void __hci_req_clear_ext_adv_sets(struct hci_request *req)
 {
 	hci_req_add(req, HCI_OP_LE_REMOVE_ADV_SET, 0, NULL);
@@ -1438,6 +1519,9 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 	struct hci_dev *hdev = req->hdev;
 	bool connectable;
 	u32 flags;
+	bdaddr_t random_addr;
+	u8 own_addr_type;
+	int err;
 	/* In ext adv set param interval is 3 octets */
 	const u8 adv_interval[3] = { 0x00, 0x08, 0x00 };
 
@@ -1452,6 +1536,16 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 	 if (!is_advertising_allowed(hdev, connectable))
 		return -EPERM;
 
+	/* Set require_privacy to true only when non-connectable
+	 * advertising is used. In that case it is fine to use a
+	 * non-resolvable private address.
+	 */
+	err = hci_get_random_address(hdev, !connectable,
+				     adv_use_rpa(hdev, flags),
+				     &own_addr_type, &random_addr);
+	if (err < 0)
+		return err;
+
 	memset(&cp, 0, sizeof(cp));
 
 	memcpy(cp.min_interval, adv_interval, sizeof(cp.min_interval));
@@ -1464,7 +1558,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 	else
 		cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);
 
-	cp.own_addr_type = BDADDR_LE_PUBLIC;
+	cp.own_addr_type = own_addr_type;
 	cp.channel_map = hdev->le_adv_channel_map;
 	cp.tx_power = 127;
 	cp.primary_phy = HCI_ADV_PHY_1M;
@@ -1473,6 +1567,21 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 
 	hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
 
+	if (own_addr_type == ADDR_LE_DEV_RANDOM &&
+	    bacmp(&random_addr, BDADDR_ANY) &&
+	    bacmp(&random_addr, &hdev->random_addr)) {
+		struct hci_cp_le_set_adv_set_rand_addr cp;
+
+		memset(&cp, 0, sizeof(cp));
+
+		cp.handle = 0;
+		bacpy(&cp.bdaddr, &random_addr);
+
+		hci_req_add(req,
+			    HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
+			    sizeof(cp), &cp);
+	}
+
 	return 0;
 }
 
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index 2451861..5329faf 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -84,6 +84,9 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
 int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
 void __hci_req_enable_ext_advertising(struct hci_request *req);
 void __hci_req_clear_ext_adv_sets(struct hci_request *req);
+int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
+			   bool use_rpa, u8 *own_addr_type,
+			   bdaddr_t *rand_addr);
 
 void __hci_req_update_class(struct hci_request *req);
 
-- 
2.7.4

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

* [PATCH v4 13/13] Bluetooth: Implement secondary advertising on different PHYs
  2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
                   ` (11 preceding siblings ...)
  2018-07-11  9:31 ` [PATCH v4 12/13] Bluetooth: Implement Set ADV set random address Jaganath Kanakkassery
@ 2018-07-11  9:31 ` Jaganath Kanakkassery
  12 siblings, 0 replies; 39+ messages in thread
From: Jaganath Kanakkassery @ 2018-07-11  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, Jaganath Kanakkassery

This patch adds support for advertising in primary and secondary
channel on different PHYs. User can add the phy preference in
the flag based on which phy type will be added in extended
advertising parameter would be set.

@ MGMT Command: Add Advertising (0x003e) plen 11
        Instance: 1
        Flags: 0x00000200
          Advertise in CODED on Secondary channel
        Duration: 0
        Timeout: 0
        Advertising data length: 0
        Scan response length: 0
< HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 2
        Extended advertising: Disabled (0x00)
        Number of sets: Disable all sets (0x00)
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
        Status: Success (0x00)
< HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25
        Handle: 0x00
        Properties: 0x0000
        Min advertising interval: 1280.000 msec (0x0800)
        Max advertising interval: 1280.000 msec (0x0800)
        Channel map: 37, 38, 39 (0x07)
        Own address type: Random (0x01)
        Peer address type: Public (0x00)
        Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
        Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
        TX power: 127 dbm (0x7f)
        Primary PHY: LE Coded (0x03)
        Secondary max skip: 0x00
        Secondary PHY: LE Coded (0x03)
        SID: 0x00
        Scan request notifications: Disabled (0x00)

Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
---
 include/net/bluetooth/hci.h  |  4 ++++
 include/net/bluetooth/mgmt.h |  6 ++++++
 net/bluetooth/hci_request.c  | 39 +++++++++++++++++++++++++++++++--------
 net/bluetooth/mgmt.c         | 18 +++++++++++++++---
 4 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 40a532a..2795c9e 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -411,6 +411,8 @@ enum {
 #define HCI_LE_SLAVE_FEATURES		0x08
 #define HCI_LE_PING			0x10
 #define HCI_LE_DATA_LEN_EXT		0x20
+#define HCI_LE_PHY_2M			0x01
+#define HCI_LE_PHY_CODED		0x08
 #define HCI_LE_EXT_ADV			0x10
 #define HCI_LE_EXT_SCAN_POLICY		0x80
 #define HCI_LE_PHY_2M			0x01
@@ -1607,6 +1609,8 @@ struct hci_cp_le_set_ext_adv_params {
 } __packed;
 
 #define HCI_ADV_PHY_1M		0X01
+#define HCI_ADV_PHY_2M		0x02
+#define HCI_ADV_PHY_CODED	0x03
 
 struct hci_rp_le_set_ext_adv_params {
 	__u8  status;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 047e98d..70b85a7 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -562,6 +562,12 @@ struct mgmt_rp_add_advertising {
 #define MGMT_ADV_FLAG_TX_POWER		BIT(4)
 #define MGMT_ADV_FLAG_APPEARANCE	BIT(5)
 #define MGMT_ADV_FLAG_LOCAL_NAME	BIT(6)
+#define MGMT_ADV_FLAG_SEC_1M 		BIT(7)
+#define MGMT_ADV_FLAG_SEC_2M 		BIT(8)
+#define MGMT_ADV_FLAG_SEC_CODED 	BIT(9)
+
+#define MGMT_ADV_FLAG_SEC_MASK	(MGMT_ADV_FLAG_SEC_1M | MGMT_ADV_FLAG_SEC_2M | \
+				 MGMT_ADV_FLAG_SEC_CODED)
 
 #define MGMT_OP_REMOVE_ADVERTISING	0x003F
 struct mgmt_cp_remove_advertising {
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 6825a65..0a8ac3e 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1522,6 +1522,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 	bdaddr_t random_addr;
 	u8 own_addr_type;
 	int err;
+	bool secondary_adv;
 	/* In ext adv set param interval is 3 octets */
 	const u8 adv_interval[3] = { 0x00, 0x08, 0x00 };
 
@@ -1551,20 +1552,42 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
 	memcpy(cp.min_interval, adv_interval, sizeof(cp.min_interval));
 	memcpy(cp.max_interval, adv_interval, sizeof(cp.max_interval));
 
-	if (connectable)
-		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);
-	else if (get_adv_instance_scan_rsp_len(hdev, instance))
-		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);
-	else
-		cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);
+	secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK);
+
+	if (connectable) {
+		if (secondary_adv)
+			cp.evt_properties = cpu_to_le16(LE_EXT_ADV_CONN_IND);
+		else
+			cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);
+	} else if (get_adv_instance_scan_rsp_len(hdev, instance)) {
+		if (secondary_adv)
+			cp.evt_properties = cpu_to_le16(LE_EXT_ADV_SCAN_IND);
+		else
+			cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);
+	} else {
+		if (secondary_adv)
+			cp.evt_properties = cpu_to_le16(LE_EXT_ADV_NON_CONN_IND);
+		else
+			cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);
+	}
 
 	cp.own_addr_type = own_addr_type;
 	cp.channel_map = hdev->le_adv_channel_map;
 	cp.tx_power = 127;
-	cp.primary_phy = HCI_ADV_PHY_1M;
-	cp.secondary_phy = HCI_ADV_PHY_1M;
 	cp.handle = 0;
 
+	if (flags & MGMT_ADV_FLAG_SEC_2M) {
+		cp.primary_phy = HCI_ADV_PHY_1M;
+		cp.secondary_phy = HCI_ADV_PHY_2M;
+	} else if (flags & MGMT_ADV_FLAG_SEC_CODED) {
+		cp.primary_phy = HCI_ADV_PHY_CODED;
+		cp.secondary_phy = HCI_ADV_PHY_CODED;
+	} else {
+		/* In all other cases use 1M */
+		cp.primary_phy = HCI_ADV_PHY_1M;
+		cp.secondary_phy = HCI_ADV_PHY_1M;
+	}
+
 	hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
 
 	if (own_addr_type == ADDR_LE_DEV_RANDOM &&
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4bc79ab..60f918a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -6356,6 +6356,16 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
 	    ext_adv_capable(hdev))
 		flags |= MGMT_ADV_FLAG_TX_POWER;
 
+	if (ext_adv_capable(hdev)) {
+		flags |= MGMT_ADV_FLAG_SEC_1M;
+
+		if (hdev->le_features[1] & HCI_LE_PHY_2M)
+			flags |= MGMT_ADV_FLAG_SEC_2M;
+
+		if (hdev->le_features[1] & HCI_LE_PHY_CODED)
+			flags |= MGMT_ADV_FLAG_SEC_CODED;
+	}
+
 	return flags;
 }
 
@@ -6561,7 +6571,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev,
 	struct mgmt_cp_add_advertising *cp = data;
 	struct mgmt_rp_add_advertising rp;
 	u32 flags;
-	u32 supported_flags;
+	u32 supported_flags, phy_flags;
 	u8 status;
 	u16 timeout, duration;
 	unsigned int prev_instance_cnt = hdev->adv_instance_cnt;
@@ -6591,10 +6601,12 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev,
 	duration = __le16_to_cpu(cp->duration);
 
 	/* The current implementation only supports a subset of the specified
-	 * flags.
+	 * flags. Also need to check mutual exclusiveness of sec flags.
 	 */
 	supported_flags = get_supported_adv_flags(hdev);
-	if (flags & ~supported_flags)
+	phy_flags = flags & MGMT_ADV_FLAG_SEC_MASK;
+	if (flags & ~supported_flags ||
+	    ((phy_flags && (phy_flags ^ (phy_flags & -phy_flags)))))
 		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
 				       MGMT_STATUS_INVALID_PARAMS);
 
-- 
2.7.4

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

* Re: [PATCH v4 01/13] Bluetooth: Define default phys in hdev and set 1M as default
  2018-07-11  9:31 ` [PATCH v4 01/13] Bluetooth: Define default phys in hdev and set 1M as default Jaganath Kanakkassery
@ 2018-07-14 16:47   ` Marcel Holtmann
  0 siblings, 0 replies; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 16:47 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> 1M would be set as default and same would be set during power on
> if controller support SetDefaultPHY.
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h      | 4 ++++
> include/net/bluetooth/hci_core.h | 3 +++
> net/bluetooth/hci_core.c         | 9 +++++----
> 3 files changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 73e48be..664fe1e 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1514,6 +1514,10 @@ struct hci_cp_le_set_default_phy {
> 	__u8    rx_phys;
> } __packed;
> 
> +#define HCI_LE_SET_PHY_1M		0x01
> +#define HCI_LE_SET_PHY_2M		0x02
> +#define HCI_LE_SET_PHY_CODED		0x04
> +

scrap the _SET here since that make no sense to me. Just call out the PHY name.

Regards

Marcel


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

* Re: [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command
  2018-07-11  9:31 ` [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command Jaganath Kanakkassery
@ 2018-07-14 17:00   ` Marcel Holtmann
  2018-07-15  7:56     ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 17:00 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This commands basically retrieve the supported packet types of
> BREDR and supported PHYs of the controller.
> 
> BR_1M_1SLOT, LE_1M_TX and LE_1M_RX would be supported by default.
> Other PHYs are supported based on the local features.
> 
> @ MGMT Command: Get PHY Configuration (0x0044) plen 0
> @ MGMT Event: Command Complete (0x0001) plen 15
>      Get PHY Configuration (0x0044) plen 12
>        Status: Success (0x00)
>        Supported PHYs: 0x7fff
>          BR 1M 1SLOT
>          BR 1M 3SLOT
>          BR 1M 5SLOT
>          EDR 2M 1SLOT
>          EDR 2M 3SLOT
>          EDR 2M 5SLOT
>          EDR 3M 1SLOT
>          EDR 3M 3SLOT
>          EDR 3M 5SLOT
>          LE 1M TX
>          LE 1M RX
>          LE 2M TX
>          LE 2M RX
>          LE CODED TX
>          LE CODED RX
>        Configurable PHYs: 0x79fe
>          BR 1M 3SLOT
>          BR 1M 5SLOT
>          EDR 2M 1SLOT
>          EDR 2M 3SLOT
>          EDR 2M 5SLOT
>          EDR 3M 1SLOT
>          EDR 3M 3SLOT
>          EDR 3M 5SLOT
>          LE 2M TX
>          LE 2M RX
>          LE CODED TX
>          LE CODED RX
>        Selected PHYs: 0x07ff
>          BR 1M 1SLOT
>          BR 1M 3SLOT
>          BR 1M 5SLOT
>          EDR 2M 1SLOT
>          EDR 2M 3SLOT
>          EDR 2M 5SLOT
>          EDR 3M 1SLOT
>          EDR 3M 3SLOT
>          EDR 3M 5SLOT
>          LE 1M TX
>          LE 1M RX
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h      |  14 ++++
> include/net/bluetooth/hci_core.h |   4 ++
> include/net/bluetooth/mgmt.h     |  24 +++++++
> net/bluetooth/mgmt.c             | 149 +++++++++++++++++++++++++++++++++++++++
> 4 files changed, 191 insertions(+)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 664fe1e..89bf800 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -291,6 +291,14 @@ enum {
> #define HCI_DH3		0x0800
> #define HCI_DH5		0x8000
> 
> +/* HCI packet types inverted masks */
> +#define HCI_2DH1	0x0002
> +#define HCI_3DH1	0x0004
> +#define HCI_2DH3	0x0100
> +#define HCI_3DH3	0x0200
> +#define HCI_2DH5	0x1000
> +#define HCI_3DH5	0x2000
> +
> #define HCI_HV1		0x0020
> #define HCI_HV2		0x0040
> #define HCI_HV3		0x0080
> @@ -354,6 +362,8 @@ enum {
> #define LMP_PCONTROL	0x04
> #define LMP_TRANSPARENT	0x08
> 
> +#define LMP_EDR_2M		0x02
> +#define LMP_EDR_3M		0x04
> #define LMP_RSSI_INQ	0x40
> #define LMP_ESCO	0x80
> 
> @@ -361,7 +371,9 @@ enum {
> #define LMP_EV5		0x02
> #define LMP_NO_BREDR	0x20
> #define LMP_LE		0x40
> +#define LMP_EDR_3SLOT	0x80
> 
> +#define LMP_EDR_5SLOT	0x01
> #define LMP_SNIFF_SUBR	0x02
> #define LMP_PAUSE_ENC	0x04
> #define LMP_EDR_ESCO_2M	0x20
> @@ -399,6 +411,8 @@ enum {
> #define HCI_LE_PING			0x10
> #define HCI_LE_DATA_LEN_EXT		0x20
> #define HCI_LE_EXT_SCAN_POLICY		0x80
> +#define HCI_LE_PHY_2M			0x01
> +#define HCI_LE_PHY_CODED		0x08
> #define HCI_LE_CHAN_SEL_ALG2		0x40

I see why you used _SET in the previous patch. Maybe it is ok to leave it that way.

> 
> /* Connection modes */
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 71f79df..a64d13f 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1141,6 +1141,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
> #define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
> #define lmp_ext_feat_capable(dev)  ((dev)->features[0][7] & LMP_EXTFEATURES)
> #define lmp_transp_capable(dev)    ((dev)->features[0][2] & LMP_TRANSPARENT)
> +#define lmp_edr_2m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_2M)
> +#define lmp_edr_3m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_3M)
> +#define lmp_edr_3slot_capable(dev) ((dev)->features[0][4] & LMP_EDR_3SLOT)
> +#define lmp_edr_5slot_capable(dev) ((dev)->features[0][5] & LMP_EDR_5SLOT)

Lets split the non-mgmt related changes from the mgmt ones into separate patches.

> 
> /* ----- Extended LMP capabilities ----- */
> #define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_MASTER)
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index e7303ee..16dddb1 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -604,6 +604,30 @@ struct mgmt_cp_set_appearance {
> } __packed;
> #define MGMT_SET_APPEARANCE_SIZE	2
> 
> +#define MGMT_OP_GET_PHY_CONFIGURATION	0x0044
> +#define MGMT_GET_PHY_CONFIGURATION_SIZE		0
> +struct mgmt_rp_get_phy_confguration {
> +	__le32	supported_phys;
> +	__le32	configurable_phys;
> +	__le32	selected_phys;
> +} __packed;
> +
> +#define MGMT_PHY_BR_1M_1SLOT	0x00000001
> +#define MGMT_PHY_BR_1M_3SLOT	0x00000002
> +#define MGMT_PHY_BR_1M_5SLOT	0x00000004
> +#define MGMT_PHY_EDR_2M_1SLOT	0x00000008
> +#define MGMT_PHY_EDR_2M_3SLOT	0x00000010
> +#define MGMT_PHY_EDR_2M_5SLOT	0x00000020
> +#define MGMT_PHY_EDR_3M_1SLOT	0x00000040
> +#define MGMT_PHY_EDR_3M_3SLOT	0x00000080
> +#define MGMT_PHY_EDR_3M_5SLOT	0x00000100
> +#define MGMT_PHY_LE_1M_TX		0x00000200
> +#define MGMT_PHY_LE_1M_RX		0x00000400
> +#define MGMT_PHY_LE_2M_TX		0x00000800
> +#define MGMT_PHY_LE_2M_RX		0x00001000
> +#define MGMT_PHY_LE_CODED_TX	0x00002000
> +#define MGMT_PHY_LE_CODED_RX	0x00004000
> +
> #define MGMT_EV_CMD_COMPLETE		0x0001
> struct mgmt_ev_cmd_complete {
> 	__le16	opcode;
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 8a80d48..4a31d4d 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -617,6 +617,126 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev,
> 				 &rp, sizeof(rp));
> }
> 
> +static u32 get_supported_phys(struct hci_dev *hdev)
> +{
> +	u32 supported_phys = 0;
> +
> +	if (lmp_bredr_capable(hdev)) {
> +		supported_phys |= MGMT_PHY_BR_1M_1SLOT;
> +
> +		if (hdev->features[0][0] & LMP_3SLOT)
> +			supported_phys |= MGMT_PHY_BR_1M_3SLOT;
> +
> +		if (hdev->features[0][0] & LMP_5SLOT)
> +			supported_phys |= MGMT_PHY_BR_1M_5SLOT;
> +
> +		if (lmp_edr_2m_capable(hdev)) {
> +			supported_phys |= MGMT_PHY_EDR_2M_1SLOT;
> +
> +			if (lmp_edr_3slot_capable(hdev))
> +				supported_phys |= MGMT_PHY_EDR_2M_3SLOT;
> +
> +			if (lmp_edr_5slot_capable(hdev))
> +				supported_phys |= MGMT_PHY_EDR_2M_5SLOT;
> +
> +			if (lmp_edr_3m_capable(hdev)) {
> +				supported_phys |= MGMT_PHY_EDR_3M_1SLOT;
> +
> +				if (lmp_edr_3slot_capable(hdev))
> +					supported_phys |= MGMT_PHY_EDR_3M_3SLOT;
> +
> +				if (lmp_edr_5slot_capable(hdev))
> +					supported_phys |= MGMT_PHY_EDR_3M_5SLOT;
> +			}
> +		}
> +	}
> +
> +	if (lmp_le_capable(hdev)) {
> +		supported_phys |= MGMT_PHY_LE_1M_TX;
> +		supported_phys |= MGMT_PHY_LE_1M_RX;
> +
> +		if (hdev->le_features[1] & HCI_LE_PHY_2M) {
> +			supported_phys |= MGMT_PHY_LE_2M_TX;
> +			supported_phys |= MGMT_PHY_LE_2M_RX;
> +		}

Extra empty line here.

> +		if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
> +			supported_phys |= MGMT_PHY_LE_CODED_TX;
> +			supported_phys |= MGMT_PHY_LE_CODED_RX;
> +		}
> +	}
> +
> +	return supported_phys;
> +}
> +
> +static u32 get_selected_phys(struct hci_dev *hdev)
> +{
> +	u32 selected_phys = 0;
> +
> +	if (lmp_bredr_capable(hdev)) {
> +		selected_phys |= MGMT_PHY_BR_1M_1SLOT;
> +
> +		if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
> +			selected_phys |= MGMT_PHY_BR_1M_3SLOT;
> +
> +		if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
> +			selected_phys |= MGMT_PHY_BR_1M_5SLOT;
> +
> +		if (lmp_edr_2m_capable(hdev)) {
> +			if (!(hdev->pkt_type & HCI_2DH1))
> +				selected_phys |= MGMT_PHY_EDR_2M_1SLOT;
> +
> +			if (lmp_edr_3slot_capable(hdev) &&
> +				!(hdev->pkt_type & HCI_2DH3))

these need to align according to the netdev coding style.

> +				selected_phys |= MGMT_PHY_EDR_2M_3SLOT;
> +
> +			if (lmp_edr_5slot_capable(hdev) &&
> +				!(hdev->pkt_type & HCI_2DH5))
> +				selected_phys |= MGMT_PHY_EDR_2M_5SLOT;
> +
> +			if (lmp_edr_3m_capable(hdev)) {
> +				if (!(hdev->pkt_type & HCI_3DH1))
> +					selected_phys |= MGMT_PHY_EDR_3M_1SLOT;
> +
> +				if (lmp_edr_3slot_capable(hdev) &&
> +					!(hdev->pkt_type & HCI_3DH3))
> +					selected_phys |= MGMT_PHY_EDR_3M_3SLOT;
> +
> +				if (lmp_edr_5slot_capable(hdev) &&
> +					!(hdev->pkt_type & HCI_3DH5))
> +					selected_phys |= MGMT_PHY_EDR_3M_5SLOT;
> +			}
> +		}
> +	}
> +
> +	if (lmp_le_capable(hdev)) {
> +		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
> +			selected_phys |= MGMT_PHY_LE_1M_TX;
> +
> +		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
> +			selected_phys |= MGMT_PHY_LE_1M_RX;
> +
> +		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
> +			selected_phys |= MGMT_PHY_LE_2M_TX;
> +
> +		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
> +			selected_phys |= MGMT_PHY_LE_2M_RX;
> +
> +		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
> +			selected_phys |= MGMT_PHY_LE_CODED_TX;
> +
> +		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
> +			selected_phys |= MGMT_PHY_LE_CODED_RX;
> +	}
> +
> +	return selected_phys;
> +}
> +
> +static u32 get_configurable_phys(struct hci_dev *hdev)
> +{
> +	return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
> +			~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);

Here the alignment needs to be also corrected.

> +}
> +
> static u32 get_supported_settings(struct hci_dev *hdev)
> {
> 	u32 settings = 0;
> @@ -654,6 +774,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
> 	    hdev->set_bdaddr)
> 		settings |= MGMT_SETTING_CONFIGURATION;
> 
> +	if (get_supported_phys(hdev) & ~(MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_LE_1M_TX |
> +					MGMT_PHY_LE_1M_RX))

Same here.

> +		settings |= MGMT_SETTING_PHY_CONFIGURATION;
> +

Frankly I think that PHY configuration can be unconditionally be listed as supported here. Even on a 4.0 or just a 1.2 device we should hint that PHY configuration is possible.

> 	return settings;
> }
> 
> @@ -722,6 +846,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
> 			settings |= MGMT_SETTING_STATIC_ADDRESS;
> 	}
> 
> +	if (phys_configured(hdev))
> +		settings |= MGMT_SETTING_PHY_CONFIGURATION;
> +

What is this conditional doing? You need to add a comment here explaining when we set configuration flag in current settings and when not.

> 	return settings;
> }
> 
> @@ -3184,6 +3311,27 @@ static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
> 	return err;
> }
> 
> +static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
> +				 void *data, u16 len)
> +{
> +	struct mgmt_rp_get_phy_confguration rp;
> +
> +	BT_DBG("sock %p %s", sk, hdev->name);
> +
> +	hci_dev_lock(hdev);
> +
> +	memset(&rp, 0, sizeof(rp));
> +
> +	rp.supported_phys = cpu_to_le32(get_supported_phys(hdev));
> +	rp.selected_phys = cpu_to_le32(get_selected_phys(hdev));
> +	rp.configurable_phys = cpu_to_le32(get_configurable_phys(hdev));
> +
> +	hci_dev_unlock(hdev);
> +
> +	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_PHY_CONFIGURATION, 0,
> +				 &rp, sizeof(rp));
> +}
> +
> static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
> 				         u16 opcode, struct sk_buff *skb)
> {
> @@ -6544,6 +6692,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
> 	{ read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE,
> 						HCI_MGMT_UNTRUSTED },
> 	{ set_appearance,	   MGMT_SET_APPEARANCE_SIZE },
> +	{ get_phy_configuration,   MGMT_GET_PHY_CONFIGURATION_SIZE },
> };

Regards

Marcel


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

* Re: [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command
  2018-07-11  9:31 ` [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command Jaganath Kanakkassery
@ 2018-07-14 17:18   ` Marcel Holtmann
  2018-07-15  9:36     ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 17:18 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This enables user to set phys which will be used in all subsequent
> connections. Also host will use the same in LE scanning as well.
> 
> This patch also implements PHY Changed event which will be
> triggered whenever default PHYs change.
> 
> This also adds PHY_CONFIGURATION to mgmt settings which set
> in the supported settings if controller supports 2/3 slot
> or 2M/#M in BREDR controller and 2M or CODED in case of LE
> and set in current settings if any of them is selected
> 
> @ MGMT Command: Set PHY Configuration (0x0045) plen 4
>        Selected PHYs: 0x7fff
>          BR 1M 1SLOT
>          BR 1M 3SLOT
>          BR 1M 5SLOT
>          EDR 2M 1SLOT
>          EDR 2M 3SLOT
>          EDR 2M 5SLOT
>          EDR 3M 1SLOT
>          EDR 3M 3SLOT
>          EDR 3M 5SLOT
>          LE 1M TX
>          LE 1M RX
>          LE 2M TX
>          LE 2M RX
>          LE CODED TX
>          LE CODED RX
> < HCI Command: LE Set Default PHY (0x08|0x0031) plen 3
>        All PHYs preference: 0x00
>        TX PHYs preference: 0x07
>          LE 1M
>          LE 2M
>          LE Coded
>        RX PHYs preference: 0x07
>          LE 1M
>          LE 2M
>          LE Coded
>> HCI Event: Command Complete (0x0e) plen 4
>      LE Set Default PHY (0x08|0x0031) ncmd 1
>        Status: Success (0x00)
> @ MGMT Event: Command Complete (0x0001) plen 3
>      Set PHY Configuration (0x0045) plen 0
>        Status: Success (0x00)
> @ MGMT Event: PHY Configuration Changed (0x0026) plen 4
>        Selected PHYs: 0x7fff
>          BR 1M 1SLOT
>          BR 1M 3SLOT
>          BR 1M 5SLOT
>          EDR 2M 1SLOT
>          EDR 2M 3SLOT
>          EDR 2M 5SLOT
>          EDR 3M 1SLOT
>          EDR 3M 3SLOT
>          EDR 3M 5SLOT
>          LE 1M TX
>          LE 1M RX
>          LE 2M TX
>          LE 2M RX
>          LE CODED TX
>          LE CODED RX
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h      |   1 +
> include/net/bluetooth/hci_core.h |   1 +
> include/net/bluetooth/mgmt.h     |  25 +++++
> net/bluetooth/hci_core.c         |   4 +
> net/bluetooth/hci_event.c        |  26 +++++
> net/bluetooth/hci_sock.c         |   1 +
> net/bluetooth/mgmt.c             | 221 +++++++++++++++++++++++++++++++++++++++
> 7 files changed, 279 insertions(+)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 89bf800..d0f7657 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -214,6 +214,7 @@ enum {
> 	HCI_MGMT_DEV_CLASS_EVENTS,
> 	HCI_MGMT_LOCAL_NAME_EVENTS,
> 	HCI_MGMT_OOB_DATA_EVENTS,
> +	HCI_MGMT_PHY_CHANGED_EVENTS,
> };

is this really needed? These flags are used for events that are conditional. Meaning they are send or not send depending on what mgmt command a given socket has called. Since PHY configuration is new and has now legacy commands it deprecates, I really wonder what this if for. So you need to explain that and if it is needed, split this out into a separate patch that explains it.

> 
> /*
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index a64d13f..ab5d494 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1544,6 +1544,7 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
> 			    u8 instance);
> void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
> 			      u8 instance);
> +int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
> 
> u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
> 		      u16 to_multiplier);
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index 16dddb1..047e98d 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -101,6 +101,7 @@ struct mgmt_rp_read_index_list {
> #define MGMT_SETTING_PRIVACY		0x00002000
> #define MGMT_SETTING_CONFIGURATION	0x00004000
> #define MGMT_SETTING_STATIC_ADDRESS	0x00008000
> +#define MGMT_SETTING_PHY_CONFIGURATION  0x00010000

You are already using this in patch 02/13 and that makes this patch series non-bisectable.

> 
> #define MGMT_OP_READ_INFO		0x0004
> #define MGMT_READ_INFO_SIZE		0
> @@ -628,6 +629,25 @@ struct mgmt_rp_get_phy_confguration {
> #define MGMT_PHY_LE_CODED_TX	0x00002000
> #define MGMT_PHY_LE_CODED_RX	0x00004000
> 
> +#define MGMT_PHY_BREDR_MASK (MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_BR_1M_3SLOT | \
> +				MGMT_PHY_BR_1M_5SLOT | MGMT_PHY_EDR_2M_1SLOT | \
> +				MGMT_PHY_EDR_2M_3SLOT | MGMT_PHY_EDR_2M_5SLOT | \
> +				MGMT_PHY_EDR_3M_1SLOT | MGMT_PHY_EDR_3M_3SLOT | \
> +				MGMT_PHY_EDR_3M_5SLOT)
> +#define MGMT_PHY_LE_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX | \
> +				MGMT_PHY_LE_2M_TX | MGMT_PHY_LE_2M_RX | \
> +				MGMT_PHY_LE_CODED_TX | MGMT_PHY_LE_CODED_RX)
> +#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
> +			     MGMT_PHY_LE_CODED_TX)
> +#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \
> +			     MGMT_PHY_LE_CODED_RX)
> +
> +#define MGMT_OP_SET_PHY_CONFIGURATION	0x0045
> +#define MGMT_SET_PHY_CONFIGURATION_SIZE		4
> +struct mgmt_cp_set_phy_confguration {
> +	__le32	selected_phys;
> +} __packed;

The _SIZE constant is normally below the data structure. Please follow the existing style.

> +
> #define MGMT_EV_CMD_COMPLETE		0x0001
> struct mgmt_ev_cmd_complete {
> 	__le16	opcode;
> @@ -848,3 +868,8 @@ struct mgmt_ev_ext_info_changed {
> 	__le16	eir_len;
> 	__u8	eir[0];
> } __packed;
> +
> +#define MGMT_EV_PHY_CONFIGURATION_CHANGED	0x0026
> +struct mgmt_ev_phy_configuration_changed {
> +	__le32	selected_phys;
> +} __packed;
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 432f89f..0d88dc9 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1924,7 +1924,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
> 		break;
> 
> 	case HCISETPTYPE:
> +		if (hdev->pkt_type == ((__u16) dr.dev_opt))
> +			break;
> +

What is the extra () doing here? I doubt that is needed.

> 		hdev->pkt_type = (__u16) dr.dev_opt;
> +		mgmt_phy_configuration_changed(hdev, NULL);
> 		break;

Also I would do that as a separate patch with a clear commit message that this is for legacy behavior. But now I see why you might need that PHY changed event flag.

So lets really do that in a separate patch to clearly point out legacy behavior and the change needed for handling it. This includes the events flag etc. One question I have is if we care if the event is send all the time or not.

So for a client this is not conflicting information or duplicated information coming along. It just means that someone changed the PHY configuration. This can happen via ioctl or mgmt and frankly an observer mgmt client wouldn't be able to tell the difference anyway. So maybe this is just overkill with no purpose.

Also we might better make mgmt_phy_configuration_changed capable of checking if an event is needed or not. Meaning it should check by itself if something changed or not. Don't remember how we did this for other functions. So something to look into.

> 
> 	case HCISETACLMTU:
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 6819215..6942315 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1042,6 +1042,28 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
> 	hci_dev_unlock(hdev);
> }
> 
> +static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> +	__u8 status = *((__u8 *) skb->data);
> +	struct hci_cp_le_set_default_phy *cp;
> +
> +	BT_DBG("%s status 0x%2.2x", hdev->name, status);
> +
> +	if (status)
> +		return;
> +
> +	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
> +	if (!cp)
> +		return;
> +
> +	hci_dev_lock(hdev);
> +
> +	hdev->le_tx_def_phys = cp->tx_phys;
> +	hdev->le_rx_def_phys = cp->rx_phys;
> +
> +	hci_dev_unlock(hdev);
> +}
> +
> static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
> {
> 	__u8 *sent, status = *((__u8 *) skb->data);
> @@ -3163,6 +3185,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
> 		hci_cc_le_set_ext_scan_enable(hdev, skb);
> 		break;
> 
> +	case HCI_OP_LE_SET_DEFAULT_PHY:
> +		hci_cc_le_set_default_phy(hdev, skb);
> +		break;
> +
> 	default:
> 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
> 		break;
> diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
> index 1506e16..476916c 100644
> --- a/net/bluetooth/hci_sock.c
> +++ b/net/bluetooth/hci_sock.c
> @@ -1328,6 +1328,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
> 			hci_sock_set_flag(sk, HCI_MGMT_SETTING_EVENTS);
> 			hci_sock_set_flag(sk, HCI_MGMT_DEV_CLASS_EVENTS);
> 			hci_sock_set_flag(sk, HCI_MGMT_LOCAL_NAME_EVENTS);
> +			hci_sock_set_flag(sk, HCI_MGMT_PHY_CHANGED_EVENTS);
> 		}
> 		break;
> 	}
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 4a31d4d..1c2ed42 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -737,6 +737,23 @@ static u32 get_configurable_phys(struct hci_dev *hdev)
> 			~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
> }
> 
> +static bool phys_configured(struct hci_dev *hdev)
> +{
> +	u32 selected_phys = get_selected_phys(hdev);
> +	u32 supported_phys = get_supported_phys(hdev);
> +
> +	/* If any of BREDR supported PHYs are deselected or
> +	 *  LE PHYs other than 1M are selected

You have extra spaces in the front.

> +	 */
> +	if (((supported_phys & MGMT_PHY_BREDR_MASK) !=
> +		 (selected_phys & MGMT_PHY_BREDR_MASK)) ||
> +		((selected_phys & MGMT_PHY_LE_MASK) &
> +		  ~(MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX)))

This alignment is not okay. Go over the character per line limit here if needed.

One question though, why are making an exception for LE_1M here?

> +		return true;
> +
> +	return false;
> +}
> +
> static u32 get_supported_settings(struct hci_dev *hdev)
> {
> 	u32 settings = 0;
> @@ -3332,6 +3349,209 @@ static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
> 				 &rp, sizeof(rp));
> }
> 
> +int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
> +{
> +	struct mgmt_ev_phy_configuration_changed ev;
> +
> +	memset(&ev, 0, sizeof(ev));
> +
> +	ev.selected_phys = cpu_to_le32(get_selected_phys(hdev));
> +
> +	return mgmt_limited_event(MGMT_EV_PHY_CONFIGURATION_CHANGED, hdev, &ev,
> +				  sizeof(ev), HCI_MGMT_PHY_CHANGED_EVENTS,
> +				  skip);
> +}
> +
> +static void set_default_phy_complete(struct hci_dev *hdev, u8 status,
> +				     u16 opcode, struct sk_buff *skb)
> +{
> +	struct mgmt_cp_set_phy_confguration *cp;
> +	struct mgmt_pending_cmd *cmd;
> +
> +	BT_DBG("status 0x%02x", status);
> +
> +	hci_dev_lock(hdev);
> +
> +	cmd = pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev);
> +	if (!cmd)
> +		goto unlock;
> +
> +	cp = cmd->param;
> +
> +	if (status) {
> +		mgmt_cmd_status(cmd->sk, hdev->id,
> +				MGMT_OP_SET_PHY_CONFIGURATION,
> +				mgmt_status(status));
> +	} else {
> +		mgmt_cmd_complete(cmd->sk, hdev->id,
> +				  MGMT_OP_SET_PHY_CONFIGURATION, 0,
> +				  NULL, 0);
> +
> +		mgmt_phy_configuration_changed(hdev, cmd->sk);
> +		new_settings(hdev, cmd->sk);

This new_settings we really need to discuss and document its behavior.

> +	}
> +
> +	mgmt_pending_remove(cmd);
> +
> +unlock:
> +	hci_dev_unlock(hdev);
> +}
> +
> +static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
> +				 void *data, u16 len)
> +{
> +	struct mgmt_cp_set_phy_confguration *cp = data;
> +	struct hci_cp_le_set_default_phy cp_phy;
> +	struct mgmt_pending_cmd *cmd;
> +	struct hci_request req;
> +	u32 selected_phys, configurable_phys, supported_phys, unconfigure_phys;
> +	u16 pkt_type = (HCI_DH1 | HCI_DM1);
> +	bool changed = false;
> +	int err;
> +
> +	BT_DBG("sock %p %s", sk, hdev->name);
> +
> +	configurable_phys = get_configurable_phys(hdev);
> +	supported_phys = get_supported_phys(hdev);
> +	selected_phys = __le32_to_cpu(cp->selected_phys);
> +
> +	if (selected_phys & ~supported_phys)
> +		return mgmt_cmd_status(sk, hdev->id,
> +				       MGMT_OP_SET_PHY_CONFIGURATION,
> +				       MGMT_STATUS_INVALID_PARAMS);
> +
> +	unconfigure_phys = supported_phys & ~configurable_phys;
> +
> +	if ((selected_phys & unconfigure_phys) != unconfigure_phys)
> +		return mgmt_cmd_status(sk, hdev->id,
> +				       MGMT_OP_SET_PHY_CONFIGURATION,
> +				       MGMT_STATUS_INVALID_PARAMS);
> +
> +	if (selected_phys == get_selected_phys(hdev))
> +		return mgmt_cmd_complete(sk, hdev->id,
> +					 MGMT_OP_SET_PHY_CONFIGURATION,
> +					 0, NULL, 0);
> +
> +	hci_dev_lock(hdev);
> +
> +	if (!hdev_is_powered(hdev)) {
> +		err = mgmt_cmd_status(sk, hdev->id,
> +				      MGMT_OP_SET_PHY_CONFIGURATION,
> +				      MGMT_STATUS_REJECTED);
> +		goto unlock;
> +	}
> +
> +	if (pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) {
> +		err = mgmt_cmd_status(sk, hdev->id,
> +				      MGMT_OP_SET_PHY_CONFIGURATION,
> +				      MGMT_STATUS_BUSY);
> +		goto unlock;
> +	}
> +
> +	if (selected_phys & MGMT_PHY_BR_1M_3SLOT)
> +		pkt_type |= (HCI_DH3 | HCI_DM3);
> +	else
> +		pkt_type &= ~(HCI_DH3 | HCI_DM3);
> +
> +	if (selected_phys & MGMT_PHY_BR_1M_5SLOT)
> +		pkt_type |= (HCI_DH5 | HCI_DM5);
> +	else
> +		pkt_type &= ~(HCI_DH5 | HCI_DM5);
> +
> +	if (selected_phys & MGMT_PHY_EDR_2M_1SLOT)
> +		pkt_type &= ~HCI_2DH1;
> +	else
> +		pkt_type |= HCI_2DH1;
> +
> +	if (selected_phys & MGMT_PHY_EDR_2M_3SLOT)
> +		pkt_type &= ~HCI_2DH3;
> +	else
> +		pkt_type |= HCI_2DH3;
> +
> +	if (selected_phys & MGMT_PHY_EDR_2M_5SLOT)
> +		pkt_type &= ~HCI_2DH5;
> +	else
> +		pkt_type |= HCI_2DH5;
> +
> +	if (selected_phys & MGMT_PHY_EDR_3M_1SLOT)
> +		pkt_type &= ~HCI_3DH1;
> +	else
> +		pkt_type |= HCI_3DH1;
> +
> +	if (selected_phys & MGMT_PHY_EDR_3M_3SLOT)
> +		pkt_type &= ~HCI_3DH3;
> +	else
> +		pkt_type |= HCI_3DH3;
> +
> +	if (selected_phys & MGMT_PHY_EDR_3M_5SLOT)
> +		pkt_type &= ~HCI_3DH5;
> +	else
> +		pkt_type |= HCI_3DH5;
> +
> +	if (pkt_type != hdev->pkt_type) {
> +		hdev->pkt_type = pkt_type;
> +		changed = true;
> +	}
> +
> +	if ((selected_phys & MGMT_PHY_LE_MASK) ==
> +		(get_selected_phys(hdev) & MGMT_PHY_LE_MASK)) {
> +		if (changed)
> +			mgmt_phy_configuration_changed(hdev, sk);
> +
> +		err = mgmt_cmd_complete(sk, hdev->id,
> +					MGMT_OP_SET_PHY_CONFIGURATION,
> +					0, NULL, 0);
> +
> +		goto unlock;
> +	}
> +
> +	cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
> +			       len);
> +	if (!cmd) {
> +		err = -ENOMEM;
> +		goto unlock;
> +	}
> +
> +	hci_req_init(&req, hdev);
> +
> +	memset(&cp_phy, 0, sizeof(cp_phy));
> +
> +	if (!(selected_phys & MGMT_PHY_LE_TX_MASK))
> +		cp_phy.all_phys |= 0x01;
> +
> +	if (!(selected_phys & MGMT_PHY_LE_RX_MASK))
> +		cp_phy.all_phys |= 0x02;
> +
> +	if (selected_phys & MGMT_PHY_LE_1M_TX)
> +		cp_phy.tx_phys |= HCI_LE_SET_PHY_1M;
> +
> +	if (selected_phys & MGMT_PHY_LE_2M_TX)
> +		cp_phy.tx_phys |= HCI_LE_SET_PHY_2M;
> +
> +	if (selected_phys & MGMT_PHY_LE_CODED_TX)
> +		cp_phy.tx_phys |= HCI_LE_SET_PHY_CODED;
> +
> +	if (selected_phys & MGMT_PHY_LE_1M_RX)
> +		cp_phy.rx_phys |= HCI_LE_SET_PHY_1M;
> +
> +	if (selected_phys & MGMT_PHY_LE_2M_RX)
> +		cp_phy.rx_phys |= HCI_LE_SET_PHY_2M;
> +
> +	if (selected_phys & MGMT_PHY_LE_CODED_RX)
> +		cp_phy.rx_phys |= HCI_LE_SET_PHY_CODED;
> +
> +	hci_req_add(&req, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(cp_phy), &cp_phy);
> +
> +	err = hci_req_run_skb(&req, set_default_phy_complete);
> +	if (err < 0)
> +		mgmt_pending_remove(cmd);
> +
> +unlock:
> +	hci_dev_unlock(hdev);
> +
> +	return err;
> +}
> +
> static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
> 				         u16 opcode, struct sk_buff *skb)
> {
> @@ -6693,6 +6913,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
> 						HCI_MGMT_UNTRUSTED },
> 	{ set_appearance,	   MGMT_SET_APPEARANCE_SIZE },
> 	{ get_phy_configuration,   MGMT_GET_PHY_CONFIGURATION_SIZE },
> +	{ set_phy_configuration,   MGMT_SET_PHY_CONFIGURATION_SIZE },
> };

Regards

Marcel


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

* Re: [PATCH v4 04/13] Bluetooth: Set Scan PHYs based on selected PHYs by user
  2018-07-11  9:31 ` [PATCH v4 04/13] Bluetooth: Set Scan PHYs based on selected PHYs by user Jaganath Kanakkassery
@ 2018-07-14 17:24   ` Marcel Holtmann
  0 siblings, 0 replies; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 17:24 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> Use the PHYs selected in Set Phy Configuration management command
> while scanning.
> 
> < HCI Command: LE Set Extended Scan Parameters (0x08|0x0041) plen 13
>        Own address type: Random (0x01)
>        Filter policy: Accept all advertisement (0x00)
>        PHYs: 0x05
>        Entry 0: LE 1M
>          Type: Active (0x01)
>          Interval: 11.250 msec (0x0012)
>          Window: 11.250 msec (0x0012)
>        Entry 1: LE Coded
>          Type: Active (0x01)
>          Interval: 11.250 msec (0x0012)
>          Window: 11.250 msec (0x0012)
>> HCI Event: Command Complete (0x0e) plen 4
>      LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1
>        Status: Success (0x00)
> < HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6
>        Extended scan: Enabled (0x01)
>        Filter duplicates: Enabled (0x01)
>        Duration: 0 msec (0x0000)
>        Period: 0.00 sec (0x0000)
>> HCI Event: Command Complete (0x0e) plen 4
>      LE Set Extended Scan Enable (0x08|0x0042) ncmd 2
>        Status: Success (0x00)
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h      |  4 +++-
> include/net/bluetooth/hci_core.h |  9 +++++++++
> net/bluetooth/hci_request.c      | 42 ++++++++++++++++++++++++++++------------
> 3 files changed, 42 insertions(+), 13 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index d0f7657..3584632 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1541,7 +1541,9 @@ struct hci_cp_le_set_ext_scan_params {
> 	__u8    data[0];
> } __packed;
> 
> -#define LE_SCAN_PHY_1M 0x01
> +#define LE_SCAN_PHY_1M		0x01
> +#define LE_SCAN_PHY_2M		0x02
> +#define LE_SCAN_PHY_CODED	0x04
> 
> struct hci_cp_le_scan_phy_params {
> 	__u8    type;
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index ab5d494..33aab89e 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1165,6 +1165,15 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
> #define bredr_sc_enabled(dev)  (lmp_sc_capable(dev) && \
> 				hci_dev_test_flag(dev, HCI_SC_ENABLED))
> 
> +#define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \
> +		      ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M))
> +
> +#define scan_2m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_2M) || \
> +		      ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_2M))
> +
> +#define scan_coded(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_CODED) || \
> +		      ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED))
> +

Lets make sure we have proper alignment here.

> /* Use ext scanning if set ext scan param and ext scan enable is supported */
> #define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \
> 			   ((dev)->commands[37] & 0x40))
> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> index faf7c71..7f5950e 100644
> --- a/net/bluetooth/hci_request.c
> +++ b/net/bluetooth/hci_request.c
> @@ -783,15 +783,13 @@ static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval,
> {
> 	struct hci_dev *hdev = req->hdev;
> 
> -	/* Use ext scanning if set ext scan param and ext scan enable is
> -	 * supported
> -	 */

Why is this comment removed?

> 	if (use_ext_scan(hdev)) {
> 		struct hci_cp_le_set_ext_scan_params *ext_param_cp;
> 		struct hci_cp_le_set_ext_scan_enable ext_enable_cp;
> 		struct hci_cp_le_scan_phy_params *phy_params;
> -		/* Ony single PHY (1M) is supported as of now */
> -		u8 data[sizeof(*ext_param_cp) + sizeof(*phy_params) * 1];
> +		u8 data[sizeof(*ext_param_cp) + sizeof(*phy_params) * 2];
> +		u32 plen;
> +		u8 scan_phys;
> 
> 		ext_param_cp = (void *)data;
> 		phy_params = (void *)ext_param_cp->data;
> @@ -799,16 +797,36 @@ static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval,
> 		memset(ext_param_cp, 0, sizeof(*ext_param_cp));
> 		ext_param_cp->own_addr_type = own_addr_type;
> 		ext_param_cp->filter_policy = filter_policy;
> -		ext_param_cp->scanning_phys = LE_SCAN_PHY_1M;
> 
> -		memset(phy_params, 0, sizeof(*phy_params));
> -		phy_params->type = type;
> -		phy_params->interval = cpu_to_le16(interval);
> -		phy_params->window = cpu_to_le16(window);
> +		plen = sizeof(*ext_param_cp);
> +
> +		if (scan_1m(hdev) || scan_2m(hdev))
> +			ext_param_cp->scanning_phys |= LE_SCAN_PHY_1M;
> +
> +		if (scan_coded(hdev))
> +			ext_param_cp->scanning_phys |= LE_SCAN_PHY_CODED;
> +
> +		scan_phys = ext_param_cp->scanning_phys;
> +
> +		while (scan_phys) {
> +			if (!(scan_phys & 0x01)) {
> +				scan_phys >>= 0x01;
> +				continue;
> +			}
> +
> +			memset(phy_params, 0, sizeof(*phy_params));
> +			phy_params->type = type;
> +			phy_params->interval = cpu_to_le16(interval);
> +			phy_params->window = cpu_to_le16(window);
> +
> +			plen += sizeof(*phy_params);
> +			phy_params++;
> +
> +			scan_phys >>= 0x01;
> +		}

This is a bit too complicated for my taste.

	if (scan_1m(..) || ..) {
		ext_param_cp->scanning_phys |= LE_SCAN_PHY_1M;

		memset(phy_params, 0, sizeof(*phy_params));
		phy_params->type = type;
		..

		plen += sizeof(*phy_params);
		phy_params++;
	}

	if (scan_coded(..)) {
		ext_param_cp->scanning_phys |= LE_SCAN_PHY_1M;

		memset(phy_params, 0, sizeof(*phy_params));
		phy_params->type = type;
		..

		plen += sizeof(*phy_params);
		phy_params++;
	}

I realize you want to avoid the double code for setting phy_params, but we might better introduce a helper for that later, but for now, lets keep it more readable.

> 
> 		hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_PARAMS,
> -			    sizeof(*ext_param_cp) + sizeof(*phy_params),
> -			    ext_param_cp);
> +			    plen, ext_param_cp);
> 
> 		memset(&ext_enable_cp, 0, sizeof(ext_enable_cp));
> 		ext_enable_cp.enable = LE_SCAN_ENABLE;

Regards

Marcel


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

* Re: [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types
  2018-07-11  9:31 ` [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types Jaganath Kanakkassery
@ 2018-07-14 17:28   ` Marcel Holtmann
  2018-07-15  9:52     ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 17:28 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This patch defines the extended ADV types and handle it in ADV report.
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h |  8 ++++++++
> net/bluetooth/hci_event.c   | 49 +++++++++++++++++++++++++++++++--------------
> 2 files changed, 42 insertions(+), 15 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 3584632..fcd1d57 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1977,6 +1977,14 @@ struct hci_ev_le_conn_complete {
> #define LE_LEGACY_SCAN_RSP_ADV		0x001b
> #define LE_LEGACY_SCAN_RSP_ADV_SCAN	0x001a
> 
> +/* Extended Advertising event types */
> +#define LE_EXT_ADV_NON_CONN_IND		0x0000
> +#define LE_EXT_ADV_CONN_IND		0x0001
> +#define LE_EXT_ADV_SCAN_IND		0x0002
> +#define LE_EXT_ADV_DIRECT_IND		0x0004
> +#define LE_EXT_ADV_SCAN_RSP		0x0008
> +#define LE_EXT_ADV_LEGACY_PDU		0x0010
> +
> #define ADDR_LE_DEV_PUBLIC	0x00
> #define ADDR_LE_DEV_RANDOM	0x01
> 
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 6942315..027abe6 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -5137,20 +5137,39 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
> 	hci_dev_unlock(hdev);
> }
> 
> -static u8 convert_legacy_evt_type(u16 evt_type)
> -{
> -	switch (evt_type) {
> -	case LE_LEGACY_ADV_IND:
> -		return LE_ADV_IND;
> -	case LE_LEGACY_ADV_DIRECT_IND:
> -		return LE_ADV_DIRECT_IND;
> -	case LE_LEGACY_ADV_SCAN_IND:
> -		return LE_ADV_SCAN_IND;
> -	case LE_LEGACY_NONCONN_IND:
> -		return LE_ADV_NONCONN_IND;
> -	case LE_LEGACY_SCAN_RSP_ADV:
> -	case LE_LEGACY_SCAN_RSP_ADV_SCAN:
> -		return LE_ADV_SCAN_RSP;
> +static u8 convert_ext_evt_type(u16 evt_type)
> +{
> +	if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
> +		switch (evt_type) {
> +		case LE_LEGACY_ADV_IND:
> +			return LE_ADV_IND;
> +		case LE_LEGACY_ADV_DIRECT_IND:
> +			return LE_ADV_DIRECT_IND;
> +		case LE_LEGACY_ADV_SCAN_IND:
> +			return LE_ADV_SCAN_IND;
> +		case LE_LEGACY_NONCONN_IND:
> +			return LE_ADV_NONCONN_IND;
> +		case LE_LEGACY_SCAN_RSP_ADV:
> +		case LE_LEGACY_SCAN_RSP_ADV_SCAN:
> +			return LE_ADV_SCAN_RSP;
> +		}

I would do a return here since only the legacy part is special.

> +	} else {
> +		if (evt_type & LE_EXT_ADV_CONN_IND) {
> +			if (evt_type & LE_EXT_ADV_DIRECT_IND)
> +				return LE_ADV_DIRECT_IND;
> +
> +			return LE_ADV_IND;
> +		}
> +
> +		if (evt_type & LE_EXT_ADV_SCAN_RSP)
> +			return LE_ADV_SCAN_RSP;
> +
> +		if (evt_type & LE_EXT_ADV_SCAN_IND)
> +			return LE_ADV_SCAN_IND;
> +
> +		if (evt_type == LE_EXT_ADV_NON_CONN_IND ||
> +		    evt_type & LE_EXT_ADV_DIRECT_IND)
> +			return LE_ADV_NONCONN_IND;

Why do we have one == match here and the rest are bit checks.

> 	}
> 
> 	BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
> @@ -5172,7 +5191,7 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
> 		u16 evt_type;
> 
> 		evt_type = __le16_to_cpu(ev->evt_type);
> -		legacy_evt_type = convert_legacy_evt_type(evt_type);
> +		legacy_evt_type = convert_ext_evt_type(evt_type);

So ext_evt_type_to_legacy might be a better function name here.

> 		if (legacy_evt_type != LE_ADV_INVALID) {

I might have asked this before, when are we reaching _INVALID here?

> 			process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
> 					   ev->bdaddr_type, NULL, 0, ev->rssi,

Regards

Marcel


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

* Re: [PATCH v4 06/13] Bluetooth: Use selected PHYs in extended connect
  2018-07-11  9:31 ` [PATCH v4 06/13] Bluetooth: Use selected PHYs in extended connect Jaganath Kanakkassery
@ 2018-07-14 17:30   ` Marcel Holtmann
  0 siblings, 0 replies; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 17:30 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> Use the selected PHYs by Set PHY Configuration management command
> in extended create connection.
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> net/bluetooth/hci_conn.c | 63 ++++++++++++++++++++++++++++++++++++------------
> 1 file changed, 47 insertions(+), 16 deletions(-)
> 
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index cc967ca..5d421a2 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -777,8 +777,9 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
> 	if (use_ext_conn(hdev)) {
> 		struct hci_cp_le_ext_create_conn *cp;
> 		struct hci_cp_le_ext_conn_param *p;
> -		/* As of now only LE 1M is supported */
> -		u8 data[sizeof(*cp) + sizeof(*p) * 1];
> +		u8 data[sizeof(*cp) + sizeof(*p) * 3];
> +		u8 init_phys;
> +		u32 plen;
> 
> 		cp = (void *) data;
> 		p = (void *) cp->data;
> @@ -788,24 +789,54 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
> 		bacpy(&cp->peer_addr, &conn->dst);
> 		cp->peer_addr_type = conn->dst_type;
> 		cp->own_addr_type = own_addr_type;
> -		cp->phys = LE_SCAN_PHY_1M;
> 
> -		memset(p, 0, sizeof(*p));
> +		if (scan_1m(hdev))
> +			cp->phys |= LE_SCAN_PHY_1M;
> 
> -		/* Set window to be the same value as the interval to enable
> -		 * continuous scanning.
> -		 */
> +		if (scan_2m(hdev))
> +			cp->phys |= LE_SCAN_PHY_2M;
> +
> +		if (scan_coded(hdev))
> +			cp->phys |= LE_SCAN_PHY_CODED;
> +
> +		init_phys = cp->phys;
> +
> +		plen = sizeof(*cp);
> +
> +		/* Use same param for all PHYs */
> +		while (init_phys) {
> +			u16 min_interval, max_interval, supv_timeout;
> 
> -		p->scan_interval = cpu_to_le16(hdev->le_scan_interval);
> -		p->scan_window = p->scan_interval;
> -		p->conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
> -		p->conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
> -		p->conn_latency = cpu_to_le16(conn->le_conn_latency);
> -		p->supervision_timeout = cpu_to_le16(conn->le_supv_timeout);
> -		p->min_ce_len = cpu_to_le16(0x0000);
> -		p->max_ce_len = cpu_to_le16(0x0000);
> +			if (!(init_phys & 0x01)) {
> +				init_phys >>= 0x01;
> +				continue;
> +			}
> +
> +			memset(p, 0, sizeof(*p));
> +
> +			/* Set window to be the same value as the interval to
> +			 * enable continuous scanning.
> +			 */
> +
> +			min_interval = conn->le_conn_min_interval;
> +			max_interval = conn->le_conn_max_interval;
> +			supv_timeout = conn->le_supv_timeout;
> +
> +			p->scan_interval = cpu_to_le16(hdev->le_scan_interval);
> +			p->scan_window = p->scan_interval;
> +			p->conn_interval_min = cpu_to_le16(min_interval);
> +			p->conn_interval_max = cpu_to_le16(max_interval);
> +			p->conn_latency = cpu_to_le16(conn->le_conn_latency);
> +			p->supervision_timeout = cpu_to_le16(supv_timeout);
> +			p->min_ce_len = cpu_to_le16(0x0000);
> +			p->max_ce_len = cpu_to_le16(0x0000);
> +
> +			p++;
> +			plen += sizeof(*p);
> +			init_phys >>= 1;
> +		}

Same comment as for the ext scan parameters one. I think we need to make this more readable since this is too complex. In addition it will make it really hard if different parameters are used for different PHYs.

Regards

Marcel


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

* Re: [PATCH v4 07/13] Bluetooth: Read no of adv sets during init
  2018-07-11  9:31 ` [PATCH v4 07/13] Bluetooth: Read no of adv sets during init Jaganath Kanakkassery
@ 2018-07-14 17:32   ` Marcel Holtmann
  2018-07-16  6:27     ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 17:32 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This patch reads the number of advertising sets in the controller
> during init and save it in hdev.
> 
> This also checks ext adv support before send Read Adv TX Power
> since legacy and extended Adv commands should not be mixed.
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h      |  7 +++++++
> include/net/bluetooth/hci_core.h |  4 ++++
> net/bluetooth/hci_core.c         | 12 ++++++++++--
> net/bluetooth/hci_event.c        | 18 ++++++++++++++++++
> 4 files changed, 39 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index fcd1d57..e584863 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -411,6 +411,7 @@ enum {
> #define HCI_LE_SLAVE_FEATURES		0x08
> #define HCI_LE_PING			0x10
> #define HCI_LE_DATA_LEN_EXT		0x20
> +#define HCI_LE_EXT_ADV			0x10
> #define HCI_LE_EXT_SCAN_POLICY		0x80
> #define HCI_LE_PHY_2M			0x01
> #define HCI_LE_PHY_CODED		0x08
> @@ -1580,6 +1581,12 @@ struct hci_cp_le_ext_conn_param {
> 	__le16 max_ce_len;
> } __packed;
> 
> +#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS	0x203b
> +struct hci_rp_le_read_num_supported_adv_sets {
> +	__u8  status;
> +	__u8  num_of_sets;
> +} __packed;
> +
> /* ---- HCI Events ---- */
> #define HCI_EV_INQUIRY_COMPLETE		0x01
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 33aab89e..e845ca6 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -222,6 +222,7 @@ struct hci_dev {
> 	__u8		le_features[8];
> 	__u8		le_white_list_size;
> 	__u8		le_resolv_list_size;
> +	__u8		le_no_of_adv_sets;

I think our style was to use _num instead of _no. See num_iac for example.

> 	__u8		le_states[8];
> 	__u8		commands[64];
> 	__u8		hci_ver;
> @@ -1180,6 +1181,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
> /* Use ext create connection if command is supported */
> #define use_ext_conn(dev) ((dev)->commands[37] & 0x80)
> 
> +/* Extended advertising support */
> +#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
> +
> /* ----- HCI protocols ----- */
> #define HCI_PROTO_DEFER             0x01
> 
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 0d88dc9..b423587 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -715,8 +715,10 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
> 		hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
> 			    events);
> 
> -		if (hdev->commands[25] & 0x40) {
> -			/* Read LE Advertising Channel TX Power */
> +		if ((hdev->commands[25] & 0x40) && !ext_adv_capable(hdev)) {
> +			/* Read LE Advertising Channel TX Power only if
> +			 * extended advertising is not supported
> +			 */
> 			hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
> 		}

Why? I prefer that we read the adv TX power always. Even if we are not using it, it is good to have it in the traces.

> @@ -750,6 +752,12 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
> 			hci_req_add(req, HCI_OP_LE_READ_DEF_DATA_LEN, 0, NULL);
> 		}
> 
> +		if (ext_adv_capable(hdev)) {
> +			/* Read LE Number of Supported Advertising Sets */
> +			hci_req_add(req, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS,
> +				    0, NULL);
> +		}
> +
> 		hci_set_le_support(req);
> 	}
> 
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 027abe6..90e7235 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1267,6 +1267,20 @@ static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
> 	le_set_scan_enable_complete(hdev, cp->enable);
> }
> 
> +static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev,
> +				      struct sk_buff *skb)
> +{
> +	struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data;
> +
> +	BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status,
> +	       rp->num_of_sets);
> +
> +	if (rp->status)
> +		return;
> +
> +	hdev->le_no_of_adv_sets = rp->num_of_sets;
> +}
> +
> static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
> 					   struct sk_buff *skb)
> {
> @@ -3189,6 +3203,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
> 		hci_cc_le_set_default_phy(hdev, skb);
> 		break;
> 
> +	case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS:
> +		hci_cc_le_read_num_adv_sets(hdev, skb);
> +		break;
> +
> 	default:
> 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
> 		break;

Regards

Marcel


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

* Re: [PATCH v4 08/13] Bluetooth: Impmlement extended adv enable
  2018-07-11  9:31 ` [PATCH v4 08/13] Bluetooth: Impmlement extended adv enable Jaganath Kanakkassery
@ 2018-07-14 18:38   ` Marcel Holtmann
  2018-07-16  8:12     ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 18:38 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This patch basically replaces legacy adv with extended adv
> based on the controller support. Currently there is no
> design change. ie only one adv set will be enabled at a time.
> 
> < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25
>        Handle: 0x00
>        Properties: 0x0010
>          Use legacy advertising PDUs: ADV_NONCONN_IND
>        Min advertising interval: 1280.000 msec (0x0800)
>        Max advertising interval: 1280.000 msec (0x0800)
>        Channel map: 37, 38, 39 (0x07)
>        Own address type: Random (0x01)
>        Peer address type: Public (0x00)
>        Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
>        Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
>        TX power: 127 dbm (0x7f)
>        Primary PHY: LE 1M (0x01)
>        Secondary max skip: 0x00
>        Secondary PHY: LE 1M (0x01)
>        SID: 0x00
>        Scan request notifications: Disabled (0x00)
>> HCI Event: Command Complete (0x0e) plen 5
>      LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1
>        Status: Success (0x00)
>        TX power (selected): 7 dbm (0x07)
> < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6
>        Extended advertising: Enabled (0x01)
>        Number of sets: 1 (0x01)
>        Entry 0
>          Handle: 0x00
>          Duration: 0 ms (0x00)
>          Max ext adv events: 0
>> HCI Event: Command Complete (0x0e) plen 4
>      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
>        Status: Success (0x00)
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h |  39 ++++++++++++
> net/bluetooth/hci_event.c   |  63 +++++++++++++++++++
> net/bluetooth/hci_request.c | 144 ++++++++++++++++++++++++++++++++++++++++----
> net/bluetooth/hci_request.h |   3 +
> net/bluetooth/mgmt.c        |  19 ++++--
> 5 files changed, 251 insertions(+), 17 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index e584863..c0c542d 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1587,6 +1587,45 @@ struct hci_rp_le_read_num_supported_adv_sets {
> 	__u8  num_of_sets;
> } __packed;
> 
> +#define HCI_OP_LE_SET_EXT_ADV_PARAMS			0x2036
> +struct hci_cp_le_set_ext_adv_params {
> +	__u8  handle;
> +	__le16 evt_properties;
> +	__u8  min_interval[3];
> +	__u8  max_interval[3];
> +	__u8  channel_map;
> +	__u8  own_addr_type;
> +	__u8  peer_addr_type;
> +	bdaddr_t  peer_addr;
> +	__u8  filter_policy;
> +	__u8  tx_power;
> +	__u8  primary_phy;
> +	__u8  secondary_max_skip;
> +	__u8  secondary_phy;
> +	__u8  sid;
> +	__u8  notif_enable;
> +} __packed;

please do proper alignment here and follow the style we currently have in hci.h.

> +
> +#define HCI_ADV_PHY_1M		0X01
> +
> +struct hci_rp_le_set_ext_adv_params {
> +	__u8  status;
> +	__u8  tx_power;
> +} __attribute__ ((packed));
> +
> +#define HCI_OP_LE_SET_EXT_ADV_ENABLE			0x2039
> +struct hci_cp_le_set_ext_adv_enable {
> +	__u8  enable;
> +	__u8  num_of_sets;
> +	__u8  data[0];
> +} __packed;
> +
> +struct hci_cp_ext_adv_set {
> +	__u8  handle;
> +	__le16 duration;
> +	__u8  max_events;
> +} __packed;
> +
> /* ---- HCI Events ---- */
> #define HCI_EV_INQUIRY_COMPLETE		0x01
> 
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 90e7235..e17002f 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1099,6 +1099,41 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
> 	hci_dev_unlock(hdev);
> }
> 
> +static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
> +					 struct sk_buff *skb)
> +{
> +	struct hci_cp_le_set_ext_adv_enable *cp;
> +	struct hci_cp_ext_adv_set *adv_set;
> +	__u8 status = *((__u8 *) skb->data);
> +
> +	BT_DBG("%s status 0x%2.2x", hdev->name, status);
> +
> +	if (status)
> +		return;
> +
> +	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
> +	if (!cp)
> +		return;
> +
> +	adv_set = (void *) cp->data;
> +
> +	hci_dev_lock(hdev);
> +
> +	if (cp->enable) {
> +		struct hci_conn *conn;
> +
> +		hci_dev_set_flag(hdev, HCI_LE_ADV);
> +
> +		conn = hci_lookup_le_connect(hdev);
> +		if (conn)
> +			queue_delayed_work(hdev->workqueue,
> +					   &conn->le_conn_timeout,
> +					   conn->conn_timeout);
> +	}
> +
> +	hci_dev_unlock(hdev);
> +}
> +
> static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
> {
> 	struct hci_cp_le_set_scan_param *cp;
> @@ -1486,6 +1521,26 @@ static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
> 	hci_dev_unlock(hdev);
> }
> 
> +static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> +	struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data;
> +	struct hci_cp_le_set_ext_adv_params *cp;
> +
> +	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
> +
> +	if (rp->status)
> +		return;
> +
> +	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
> +	if (!cp)
> +		return;
> +
> +	hci_dev_lock(hdev);
> +	hdev->adv_addr_type = cp->own_addr_type;
> +	hdev->adv_tx_power = rp->tx_power;

Don't do this. The adv_tx_power is meant for the default adv TX power of the controller. This can not be overwritten. Leave this alone for now. I realize that you want this to support the TX power data type, but that needs to be stored in the adv instance then. And then used from there.

So create a pre-change that has the tx_power information in the adv instance. And on instance populate it using hdev->adv_tx_power. Use that also for ext adv parameters and when the parameter setting comes back then update the value with the controller chosen TX power. So that adv data has the correct value in there.

Please note that in case of not using legacy advertising and actually transmitting TX power via ext adv, then we need to make sure it is not included in the adv data.

> +	hci_dev_unlock(hdev);
> +}
> +
> static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
> {
> 	struct hci_rp_read_rssi *rp = (void *) skb->data;
> @@ -3207,6 +3262,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
> 		hci_cc_le_read_num_adv_sets(hdev, skb);
> 		break;
> 
> +	case HCI_OP_LE_SET_EXT_ADV_PARAMS:
> +		hci_cc_set_ext_adv_param(hdev, skb);
> +		break;
> +
> +	case HCI_OP_LE_SET_EXT_ADV_ENABLE:
> +		hci_cc_le_set_ext_adv_enable(hdev, skb);
> +		break;
> +
> 	default:
> 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
> 		break;
> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> index 7f5950e..a2091b5 100644
> --- a/net/bluetooth/hci_request.c
> +++ b/net/bluetooth/hci_request.c
> @@ -894,6 +894,24 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
> 			   hdev->le_scan_window, own_addr_type, filter_policy);
> }
> 
> +static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
> +{
> +	struct adv_info *adv_instance;
> +
> +	/* Ignore instance 0 */
> +	if (instance == 0x00)
> +		return 0;
> +
> +	adv_instance = hci_find_adv_instance(hdev, instance);
> +	if (!adv_instance)
> +		return 0;
> +
> +	/* TODO: Take into account the "appearance" and "local-name" flags here.
> +	 * These are currently being ignored as they are not supported.
> +	 */
> +	return adv_instance->scan_rsp_len;
> +}
> +
> static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
> {
> 	u8 instance = hdev->cur_adv_instance;
> @@ -1303,9 +1321,13 @@ void hci_req_reenable_advertising(struct hci_dev *hdev)
> 		__hci_req_schedule_adv_instance(&req, hdev->cur_adv_instance,
> 						true);
> 	} else {
> -		__hci_req_update_adv_data(&req, 0x00);
> -		__hci_req_update_scan_rsp_data(&req, 0x00);
> -		__hci_req_enable_advertising(&req);
> +		if (ext_adv_capable(hdev)) {
> +			__hci_req_start_ext_adv(&req, 0x00);
> +		} else {
> +			__hci_req_update_adv_data(&req, 0x00);
> +			__hci_req_update_scan_rsp_data(&req, 0x00);
> +			__hci_req_enable_advertising(&req);
> +		}
> 	}
> 
> 	hci_req_run(&req, adv_enable_complete);
> @@ -1342,6 +1364,88 @@ static void adv_timeout_expire(struct work_struct *work)
> 	hci_dev_unlock(hdev);
> }
> 
> +static int __hci_req_setup_ext_adv_instance(struct hci_request *req,
> +					    u8 instance)
> +{
> +	struct hci_cp_le_set_ext_adv_params cp;
> +	struct hci_dev *hdev = req->hdev;
> +	bool connectable;
> +	u32 flags;
> +	/* In ext adv set param interval is 3 octets */
> +	const u8 adv_interval[3] = { 0x00, 0x08, 0x00 };
> +
> +	flags = get_adv_instance_flags(hdev, instance);
> +
> +	/* If the "connectable" instance flag was not set, then choose between
> +	 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
> +	 */
> +	connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
> +		      mgmt_get_connectable(hdev);
> +
> +	 if (!is_advertising_allowed(hdev, connectable))
> +		return -EPERM;
> +
> +	memset(&cp, 0, sizeof(cp));
> +
> +	memcpy(cp.min_interval, adv_interval, sizeof(cp.min_interval));
> +	memcpy(cp.max_interval, adv_interval, sizeof(cp.max_interval));
> +
> +	if (connectable)
> +		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);
> +	else if (get_adv_instance_scan_rsp_len(hdev, instance))
> +		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);
> +	else
> +		cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);
> +
> +	cp.own_addr_type = BDADDR_LE_PUBLIC;
> +	cp.channel_map = hdev->le_adv_channel_map;
> +	cp.tx_power = 127;
> +	cp.primary_phy = HCI_ADV_PHY_1M;
> +	cp.secondary_phy = HCI_ADV_PHY_1M;
> +	cp.handle = 0;
> +
> +	hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
> +
> +	return 0;
> +}
> +
> +void __hci_req_enable_ext_advertising(struct hci_request *req)
> +{
> +	struct hci_cp_le_set_ext_adv_enable *cp;
> +	struct hci_cp_ext_adv_set *adv_set;
> +	u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
> +
> +	cp = (void *) data;
> +	adv_set = (void *) cp->data;
> +
> +	memset(cp, 0, sizeof(*cp));
> +
> +	cp->enable = 0x01;
> +	cp->num_of_sets = 0x01;
> +
> +	memset(adv_set, 0, sizeof(*adv_set));
> +
> +	adv_set->handle = 0;
> +
> +	hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE,
> +		    sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
> +		    data);
> +}
> +
> +int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
> +{
> +	struct hci_dev *hdev = req->hdev;
> +	int err;
> +
> +	err = __hci_req_setup_ext_adv_instance(req, instance);
> +	if (err < 0)
> +		return err;
> +
> +	__hci_req_enable_ext_advertising(req);
> +
> +	return 0;
> +}
> +
> int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
> 				    bool force)
> {
> @@ -1395,9 +1499,13 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
> 		return 0;
> 
> 	hdev->cur_adv_instance = instance;
> -	__hci_req_update_adv_data(req, instance);
> -	__hci_req_update_scan_rsp_data(req, instance);
> -	__hci_req_enable_advertising(req);
> +	if (ext_adv_capable(hdev)) {
> +		__hci_req_start_ext_adv(req, instance);
> +	} else {
> +		__hci_req_update_adv_data(req, instance);
> +		__hci_req_update_scan_rsp_data(req, instance);
> +		__hci_req_enable_advertising(req);
> +	}
> 
> 	return 0;
> }
> @@ -1668,8 +1776,12 @@ static int connectable_update(struct hci_request *req, unsigned long opt)
> 
> 	/* Update the advertising parameters if necessary */
> 	if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
> -	    !list_empty(&hdev->adv_instances))
> -		__hci_req_enable_advertising(req);
> +	    !list_empty(&hdev->adv_instances)) {
> +		if (ext_adv_capable(hdev))
> +			__hci_req_start_ext_adv(req, hdev->cur_adv_instance);
> +		else
> +			__hci_req_enable_advertising(req);
> +	}
> 
> 	__hci_update_background_scan(req);
> 
> @@ -1778,8 +1890,12 @@ static int discoverable_update(struct hci_request *req, unsigned long opt)
> 		/* Discoverable mode affects the local advertising
> 		 * address in limited privacy mode.
> 		 */
> -		if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY))
> -			__hci_req_enable_advertising(req);
> +		if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) {
> +			if (ext_adv_capable(hdev))
> +				__hci_req_start_ext_adv(req, 0x00);
> +			else
> +				__hci_req_enable_advertising(req);
> +		}
> 	}
> 
> 	hci_dev_unlock(hdev);
> @@ -2375,8 +2491,12 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
> 			__hci_req_update_adv_data(req, 0x00);
> 			__hci_req_update_scan_rsp_data(req, 0x00);
> 
> -			if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
> -				__hci_req_enable_advertising(req);
> +			if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
> +				if (ext_adv_capable(hdev))
> +					__hci_req_start_ext_adv(req, 0x00);
> +				else
> +					__hci_req_enable_advertising(req);
> +			}
> 		} else if (!list_empty(&hdev->adv_instances)) {
> 			struct adv_info *adv_instance;
> 
> diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
> index 702beb1..9b8c74d 100644
> --- a/net/bluetooth/hci_request.h
> +++ b/net/bluetooth/hci_request.h
> @@ -80,6 +80,9 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
> 				struct hci_request *req, u8 instance,
> 				bool force);
> 
> +int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
> +void __hci_req_enable_ext_advertising(struct hci_request *req);
> +
> void __hci_req_update_class(struct hci_request *req);
> 
> /* Returns true if HCI commands were queued */
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 1c2ed42..22997f8 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -961,7 +961,10 @@ static void rpa_expired(struct work_struct *work)
> 	 * function.
> 	 */
> 	hci_req_init(&req, hdev);
> -	__hci_req_enable_advertising(&req);
> +	if (ext_adv_capable(hdev))
> +		__hci_req_start_ext_adv(&req, hdev->cur_adv_instance);
> +	elsey
> +		__hci_req_enable_advertising(&req);
> 	hci_req_run(&req, NULL);
> }
> 
> @@ -4405,9 +4408,14 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
> 		 * HCI_ADVERTISING flag is not yet set.
> 		 */
> 		hdev->cur_adv_instance = 0x00;
> -		__hci_req_update_adv_data(&req, 0x00);
> -		__hci_req_update_scan_rsp_data(&req, 0x00);
> -		__hci_req_enable_advertising(&req);
> +
> +		if (ext_adv_capable(hdev)) {
> +			__hci_req_start_ext_adv(&req, 0x00);
> +		} else {
> +			__hci_req_update_adv_data(&req, 0x00);
> +			__hci_req_update_scan_rsp_data(&req, 0x00);
> +			__hci_req_enable_advertising(&req);
> +		}
> 	} else {
> 		__hci_req_disable_advertising(&req);
> 	}
> @@ -6335,7 +6343,8 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
> 	flags |= MGMT_ADV_FLAG_APPEARANCE;
> 	flags |= MGMT_ADV_FLAG_LOCAL_NAME;
> 
> -	if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
> +	if ((hdev->adv_tx_power != HCI_TX_POWER_INVALID) ||
> +	    ext_adv_capable(hdev))
> 		flags |= MGMT_ADV_FLAG_TX_POWER;

See comments above on how this needs to be handled differently.

Regards

Marcel


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

* Re: [PATCH v4 09/13] Bluetooth: Use Set ext adv/scan rsp data if controller supports
  2018-07-11  9:31 ` [PATCH v4 09/13] Bluetooth: Use Set ext adv/scan rsp data if controller supports Jaganath Kanakkassery
@ 2018-07-14 18:47   ` Marcel Holtmann
  0 siblings, 0 replies; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 18:47 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This patch implements Set Ext Adv data and Set Ext Scan rsp data
> if controller support extended advertising.
> 
> Currently the operation is set as Complete data and fragment
> preference is set as no fragment
> 
> < HCI Command: LE Set Extended Advertising Data (0x08|0x0037) plen 35
>        Handle: 0x00
>        Operation: Complete extended advertising data (0x03)
>        Fragment preference: Minimize fragmentation (0x01)
>        Data length: 0x15
>        16-bit Service UUIDs (complete): 2 entries
>          Heart Rate (0x180d)
>          Battery Service (0x180f)
>        Name (complete): Test LE
>        Company: Google (224)
>          Data: 0102
>> HCI Event: Command Complete (0x0e) plen 4
>      LE Set Extended Advertising Data (0x08|0x0037) ncmd 1
>        Status: Success (0x00)
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h |  22 ++++++++
> net/bluetooth/hci_request.c | 124 +++++++++++++++++++++++++++++++++-----------
> net/bluetooth/hci_request.h |   1 +
> net/bluetooth/mgmt.c        |  10 +++-
> 4 files changed, 124 insertions(+), 33 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index c0c542d..5b84d9a 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1626,6 +1626,28 @@ struct hci_cp_ext_adv_set {
> 	__u8  max_events;
> } __packed;
> 
> +#define HCI_OP_LE_SET_EXT_ADV_DATA		0x2037
> +struct hci_cp_le_set_ext_adv_data {
> +	__u8  handle;
> +	__u8  operation;
> +	__u8  fragment_preference;

using frag_pref would be better here.

> +	__u8  length;
> +	__u8  data[HCI_MAX_AD_LENGTH];
> +} __packed;
> +
> +#define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA		0x2038
> +struct hci_cp_le_set_ext_scan_rsp_data {
> +	__u8  handle;
> +	__u8  operation;
> +	__u8  fragment_preference;
> +	__u8  length;
> +	__u8  data[HCI_MAX_AD_LENGTH];
> +} __packed;
> +
> +#define LE_SET_ADV_DATA_OP_COMPLETE	0x03
> +
> +#define LE_SET_ADV_DATA_NO_FRAG		0x01
> +
> /* ---- HCI Events ---- */
> #define HCI_EV_INQUIRY_COMPLETE		0x01
> 
> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> index a2091b5..5fde161 100644
> --- a/net/bluetooth/hci_request.c
> +++ b/net/bluetooth/hci_request.c
> @@ -1173,29 +1173,58 @@ static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
> void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
> {
> 	struct hci_dev *hdev = req->hdev;
> -	struct hci_cp_le_set_scan_rsp_data cp;
> 	u8 len;
> 
> 	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
> 		return;
> 
> -	memset(&cp, 0, sizeof(cp));
> +	if (ext_adv_capable(hdev)) {
> +		struct hci_cp_le_set_ext_scan_rsp_data cp;
> 
> -	if (instance)
> -		len = create_instance_scan_rsp_data(hdev, instance, cp.data);
> -	else
> -		len = create_default_scan_rsp_data(hdev, cp.data);
> +		memset(&cp, 0, sizeof(cp));
> 
> -	if (hdev->scan_rsp_data_len == len &&
> -	    !memcmp(cp.data, hdev->scan_rsp_data, len))
> -		return;
> +		if (instance)
> +			len = create_instance_scan_rsp_data(hdev, instance,
> +							    cp.data);
> +		else
> +			len = create_default_scan_rsp_data(hdev, cp.data);
> +
> +		if (hdev->scan_rsp_data_len == len &&
> +		    !memcmp(cp.data, hdev->scan_rsp_data, len))
> +			return;
> +
> +		memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
> +		hdev->scan_rsp_data_len = len;
> +
> +		cp.handle = 0;
> +		cp.length = len;
> +		cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
> +		cp.fragment_preference = LE_SET_ADV_DATA_NO_FRAG;
> 
> -	memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
> -	hdev->scan_rsp_data_len = len;
> +		hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, sizeof(cp),
> +			    &cp);
> +	} else {
> +		struct hci_cp_le_set_scan_rsp_data cp;
> +
> +		memset(&cp, 0, sizeof(cp));
> +
> +		if (instance)
> +			len = create_instance_scan_rsp_data(hdev, instance,
> +							    cp.data);
> +		else
> +			len = create_default_scan_rsp_data(hdev, cp.data);
> +
> +		if (hdev->scan_rsp_data_len == len &&
> +		    !memcmp(cp.data, hdev->scan_rsp_data, len))
> +			return;
> 
> -	cp.length = len;
> +		memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
> +		hdev->scan_rsp_data_len = len;
> 
> -	hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
> +		cp.length = len;
> +
> +		hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
> +	}
> }
> 
> static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
> @@ -1269,27 +1298,51 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
> void __hci_req_update_adv_data(struct hci_request *req, u8 instance)
> {
> 	struct hci_dev *hdev = req->hdev;
> -	struct hci_cp_le_set_adv_data cp;
> 	u8 len;
> 
> 	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
> 		return;
> 
> -	memset(&cp, 0, sizeof(cp));
> +	if (ext_adv_capable(hdev)) {
> +		struct hci_cp_le_set_ext_adv_data cp;
> 
> -	len = create_instance_adv_data(hdev, instance, cp.data);
> +		memset(&cp, 0, sizeof(cp));
> 
> -	/* There's nothing to do if the data hasn't changed */
> -	if (hdev->adv_data_len == len &&
> -	    memcmp(cp.data, hdev->adv_data, len) == 0)
> -		return;
> +		len = create_instance_adv_data(hdev, instance, cp.data);
> +
> +		/* There's nothing to do if the data hasn't changed */
> +		if (hdev->adv_data_len == len &&
> +		    memcmp(cp.data, hdev->adv_data, len) == 0)
> +			return;
> +
> +		memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
> +		hdev->adv_data_len = len;
> +
> +		cp.length = len;
> +		cp.handle = 0;
> +		cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
> +		cp.fragment_preference = LE_SET_ADV_DATA_NO_FRAG;
> +
> +		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(cp), &cp);
> +	} else {
> +		struct hci_cp_le_set_adv_data cp;
> 
> -	memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
> -	hdev->adv_data_len = len;
> +		memset(&cp, 0, sizeof(cp));
> +
> +		len = create_instance_adv_data(hdev, instance, cp.data);
> +
> +		/* There's nothing to do if the data hasn't changed */
> +		if (hdev->adv_data_len == len &&
> +		    memcmp(cp.data, hdev->adv_data, len) == 0)
> +			return;
> +
> +		memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
> +		hdev->adv_data_len = len;
> 
> -	cp.length = len;
> +		cp.length = len;
> 
> -	hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
> +		hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
> +	}
> }
> 
> int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance)
> @@ -1364,8 +1417,7 @@ static void adv_timeout_expire(struct work_struct *work)
> 	hci_dev_unlock(hdev);
> }
> 
> -static int __hci_req_setup_ext_adv_instance(struct hci_request *req,
> -					    u8 instance)
> +int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
> {
> 	struct hci_cp_le_set_ext_adv_params cp;
> 	struct hci_dev *hdev = req->hdev;
> @@ -1441,6 +1493,8 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
> 	if (err < 0)
> 		return err;
> 
> +	__hci_req_update_adv_data(req, instance);
> +	__hci_req_update_scan_rsp_data(req, instance);
> 	__hci_req_enable_ext_advertising(req);
> 
> 	return 0;
> @@ -2488,14 +2542,22 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
> 		 */
> 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
> 		    list_empty(&hdev->adv_instances)) {
> -			__hci_req_update_adv_data(req, 0x00);
> -			__hci_req_update_scan_rsp_data(req, 0x00);
> +			int err = 0;
> +
> +			if (ext_adv_capable(hdev))
> +				err = __hci_req_setup_ext_adv_instance(req,
> +								       0x00);
> +
> +			if (!err) {
> +				__hci_req_update_adv_data(req, 0x00);
> +				__hci_req_update_scan_rsp_data(req, 0x00);
> +			}
> 
> 			if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
> -				if (ext_adv_capable(hdev))
> -					__hci_req_start_ext_adv(req, 0x00);
> -				else
> +				if (!ext_adv_capable(hdev))
> 					__hci_req_enable_advertising(req);
> +				else if (!err)
> +					__hci_req_enable_ext_advertising(req);
> 			}
> 		} else if (!list_empty(&hdev->adv_instances)) {
> 			struct adv_info *adv_instance;
> diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
> index 9b8c74d..6afc624 100644
> --- a/net/bluetooth/hci_request.h
> +++ b/net/bluetooth/hci_request.h
> @@ -80,6 +80,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
> 				struct hci_request *req, u8 instance,
> 				bool force);
> 
> +int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
> int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
> void __hci_req_enable_ext_advertising(struct hci_request *req);
> 
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 22997f8..ed7f35d 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -1868,10 +1868,16 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
> 	 */
> 	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
> 		struct hci_request req;
> +		int err = 0;
> 
> 		hci_req_init(&req, hdev);
> -		__hci_req_update_adv_data(&req, 0x00);
> -		__hci_req_update_scan_rsp_data(&req, 0x00);
> +		if (ext_adv_capable(hdev))
> +			err = __hci_req_setup_ext_adv_instance(&req, 0x00);

		else
			err = 0;

And just do int err; above for the variable declaration.

> +
> +		if (!err) {
> +			__hci_req_update_adv_data(&req, 0x00);
> +			__hci_req_update_scan_rsp_data(&req, 0x00);
> +		}
> 		hci_req_run(&req, NULL);
> 		hci_update_background_scan(hdev);
> 	}

Regards

Marcel


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

* Re: [PATCH v4 10/13] Bluetooth: Implement disable and removal of adv instance
  2018-07-11  9:31 ` [PATCH v4 10/13] Bluetooth: Implement disable and removal of adv instance Jaganath Kanakkassery
@ 2018-07-14 18:50   ` Marcel Holtmann
  2018-07-16  8:21     ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 18:50 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> If ext adv is enabled then use ext adv to disable as well.
> Also remove the adv set during LE disable.
> 
> < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 2
>        Extended advertising: Disabled (0x00)
>        Number of sets: Disable all sets (0x00)
>> HCI Event: Command Complete (0x0e) plen 4
>      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
>        Status: Success (0x00)
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h |  7 +++++++
> net/bluetooth/hci_event.c   |  2 ++
> net/bluetooth/hci_request.c | 22 ++++++++++++++++++++--
> net/bluetooth/hci_request.h |  1 +
> net/bluetooth/mgmt.c        |  3 +++
> 5 files changed, 33 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 5b84d9a..1a68530 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1648,6 +1648,13 @@ struct hci_cp_le_set_ext_scan_rsp_data {
> 
> #define LE_SET_ADV_DATA_NO_FRAG		0x01
> 
> +#define HCI_OP_LE_REMOVE_ADV_SET	0x203c
> +struct hci_cp_le_remove_adv_set {
> +	__u8  handle;
> +} __packed;
> +
> +#define HCI_OP_LE_CLEAR_ADV_SETS	0x203d
> +
> /* ---- HCI Events ---- */
> #define HCI_EV_INQUIRY_COMPLETE		0x01
> 
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index e17002f..e703880 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1129,6 +1129,8 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
> 			queue_delayed_work(hdev->workqueue,
> 					   &conn->le_conn_timeout,
> 					   conn->conn_timeout);
> +	} else {
> +		hci_dev_clear_flag(hdev, HCI_LE_ADV);
> 	}
> 
> 	hci_dev_unlock(hdev);
> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> index 5fde161..7051c5b 100644
> --- a/net/bluetooth/hci_request.c
> +++ b/net/bluetooth/hci_request.c
> @@ -933,9 +933,19 @@ static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
> 
> void __hci_req_disable_advertising(struct hci_request *req)
> {
> -	u8 enable = 0x00;
> +	if (ext_adv_capable(req->hdev)) {
> +		struct hci_cp_le_set_ext_adv_enable cp;
> 
> -	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
> +		cp.enable = 0x00;
> +		/* Disable all adv sets */
> +		cp.num_of_sets = 0x00;

I would prefer a more details comment that we can disable all sets since we only support one set at the moment anyway.

> +
> +		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(cp), &cp);
> +	} else {
> +		u8 enable = 0x00;
> +
> +		hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
> +	}
> }
> 
> static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
> @@ -1417,6 +1427,11 @@ static void adv_timeout_expire(struct work_struct *work)
> 	hci_dev_unlock(hdev);
> }
> 
> +void __hci_req_clear_ext_adv_sets(struct hci_request *req)
> +{
> +	hci_req_add(req, HCI_OP_LE_REMOVE_ADV_SET, 0, NULL);

Actually this needs a comment as well to note that this is fine since we are just using a single set at the moment.

> +}
> +
> int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
> {
> 	struct hci_cp_le_set_ext_adv_params cp;
> @@ -1489,6 +1504,9 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
> 	struct hci_dev *hdev = req->hdev;
> 	int err;
> 
> +	if (hci_dev_test_flag(hdev, HCI_LE_ADV))
> +		__hci_req_disable_advertising(req);
> +
> 	err = __hci_req_setup_ext_adv_instance(req, instance);
> 	if (err < 0)
> 		return err;
> diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
> index 6afc624..2451861 100644
> --- a/net/bluetooth/hci_request.h
> +++ b/net/bluetooth/hci_request.h
> @@ -83,6 +83,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
> int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
> int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
> void __hci_req_enable_ext_advertising(struct hci_request *req);
> +void __hci_req_clear_ext_adv_sets(struct hci_request *req);
> 
> void __hci_req_update_class(struct hci_request *req);
> 
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index ed7f35d..4bc79ab 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -1976,6 +1976,9 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
> 	} else {
> 		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
> 			__hci_req_disable_advertising(&req);
> +
> +		if (ext_adv_capable(hdev))
> +			__hci_req_clear_ext_adv_sets(&req);
> 	}
> 
> 	hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),

Regards

Marcel


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

* Re: [PATCH v4 11/13] Bluetooth: Use ext adv for directed adv
  2018-07-11  9:31 ` [PATCH v4 11/13] Bluetooth: Use ext adv for directed adv Jaganath Kanakkassery
@ 2018-07-14 18:56   ` Marcel Holtmann
  0 siblings, 0 replies; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 18:56 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This patch does extended advertising for directed advertising
> if the controller supportes. Instance 0 is used for directed
> advertising.
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> net/bluetooth/hci_conn.c | 67 ++++++++++++++++++++++++++++++++----------------
> 1 file changed, 45 insertions(+), 22 deletions(-)
> 
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 5d421a2..fc27bd8 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -870,35 +870,58 @@ static void hci_req_directed_advertising(struct hci_request *req,
> 					 struct hci_conn *conn)
> {
> 	struct hci_dev *hdev = req->hdev;
> -	struct hci_cp_le_set_adv_param cp;
> 	u8 own_addr_type;
> 	u8 enable;
> 
> -	/* Clear the HCI_LE_ADV bit temporarily so that the
> -	 * hci_update_random_address knows that it's safe to go ahead
> -	 * and write a new random address. The flag will be set back on
> -	 * as soon as the SET_ADV_ENABLE HCI command completes.
> -	 */
> -	hci_dev_clear_flag(hdev, HCI_LE_ADV);
> +	if (ext_adv_capable(hdev)) {
> +		struct hci_cp_le_set_ext_adv_params cp;
> 
> -	/* Set require_privacy to false so that the remote device has a
> -	 * chance of identifying us.
> -	 */
> -	if (hci_update_random_address(req, false, conn_use_rpa(conn),
> -				      &own_addr_type) < 0)
> -		return;
> +		memset(&cp, 0, sizeof(cp));
> 
> -	memset(&cp, 0, sizeof(cp));
> -	cp.type = LE_ADV_DIRECT_IND;
> -	cp.own_address_type = own_addr_type;
> -	cp.direct_addr_type = conn->dst_type;
> -	bacpy(&cp.direct_addr, &conn->dst);
> -	cp.channel_map = hdev->le_adv_channel_map;
> +		cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_DIRECT_IND);
> +		cp.own_addr_type = own_addr_type;
> +		cp.channel_map = hdev->le_adv_channel_map;
> +		cp.tx_power = 127;

Use the proper constant here. Or maybe we actually want to use hdev->adv_tx_power here instead. As I mentioned in early patches we want to keep the behavior of what legacy advertising does.

> +		cp.primary_phy = HCI_ADV_PHY_1M;
> +		cp.secondary_phy = HCI_ADV_PHY_1M;
> +		cp.handle = 0; /* Use instance 0 for directed adv */
> +		cp.own_addr_type = own_addr_type;
> +		cp.peer_addr_type = conn->dst_type;
> +		bacpy(&cp.peer_addr, &conn->dst);
> +
> +		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
> 
> -	hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
> +		__hci_req_enable_ext_advertising(req);
> +	} else {
> +		struct hci_cp_le_set_adv_param cp;
> +
> +		/* Clear the HCI_LE_ADV bit temporarily so that the
> +		 * hci_update_random_address knows that it's safe to go ahead
> +		 * and write a new random address. The flag will be set back on
> +		 * as soon as the SET_ADV_ENABLE HCI command completes.
> +		 */
> +		hci_dev_clear_flag(hdev, HCI_LE_ADV);
> 
> -	enable = 0x01;
> -	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
> +		/* Set require_privacy to false so that the remote device has a
> +		 * chance of identifying us.
> +		 */
> +		if (hci_update_random_address(req, false, conn_use_rpa(conn),
> +					      &own_addr_type) < 0)
> +			return;
> +
> +		memset(&cp, 0, sizeof(cp));
> +		cp.type = LE_ADV_DIRECT_IND;
> +		cp.own_address_type = own_addr_type;
> +		cp.direct_addr_type = conn->dst_type;
> +		bacpy(&cp.direct_addr, &conn->dst);
> +		cp.channel_map = hdev->le_adv_channel_map;
> +
> +		hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
> +
> +		enable = 0x01;
> +		hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
> +			    &enable);
> +	}
> 
> 	conn->state = BT_CONNECT;
> }

Regards

Marcel


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

* Re: [PATCH v4 12/13] Bluetooth: Implement Set ADV set random address
  2018-07-11  9:31 ` [PATCH v4 12/13] Bluetooth: Implement Set ADV set random address Jaganath Kanakkassery
@ 2018-07-14 20:52   ` Marcel Holtmann
  2018-07-16  9:57     ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-14 20:52 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth, Jaganath Kanakkassery

Hi Jaganath,

> This basically sets the random address for the instance 0.
> Random address can be set only if the instance is created which
> is done in Set ext adv param.
> 
> This introduces a hci_get_random_address() which returns the
> own address type and random address (rpa, nrpa or static) based
> on the instance flags and hdev flags. New function is required
> since own address type should be known before setting adv params
> but address can be set only after setting params.
> 
> < HCI Command: LE Set Advertising Set Random Address (0x08|0x0035) plen 7
>        Advertising handle: 0x00
>        Advertising random address: 3C:8E:56:9B:77:84 (OUI 3C-8E-56)
>> HCI Event: Command Complete (0x0e) plen 4
>      LE Set Advertising Set Random Address (0x08|0x0035) ncmd 1
>        Status: Success (0x00)
> 
> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
> ---
> include/net/bluetooth/hci.h |   6 +++
> net/bluetooth/hci_conn.c    |  23 +++++++++
> net/bluetooth/hci_event.c   |  24 ++++++++++
> net/bluetooth/hci_request.c | 111 +++++++++++++++++++++++++++++++++++++++++++-
> net/bluetooth/hci_request.h |   3 ++
> 5 files changed, 166 insertions(+), 1 deletion(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 1a68530..40a532a 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1655,6 +1655,12 @@ struct hci_cp_le_remove_adv_set {
> 
> #define HCI_OP_LE_CLEAR_ADV_SETS	0x203d
> 
> +#define HCI_OP_LE_SET_ADV_SET_RAND_ADDR	0x2035
> +struct hci_cp_le_set_adv_set_rand_addr {
> +	__u8  handle;
> +	bdaddr_t  bdaddr;
> +} __packed;
> +
> /* ---- HCI Events ---- */
> #define HCI_EV_INQUIRY_COMPLETE		0x01
> 
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index fc27bd8..cf180b24 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -875,6 +875,14 @@ static void hci_req_directed_advertising(struct hci_request *req,
> 
> 	if (ext_adv_capable(hdev)) {
> 		struct hci_cp_le_set_ext_adv_params cp;
> +		bdaddr_t random_addr;
> +
> +		/* Set require_privacy to false so that the remote device has a
> +		 * chance of identifying us.
> +		 */
> +		if (hci_get_random_address(hdev, false, conn_use_rpa(conn),
> +					   &own_addr_type, &random_addr) < 0)
> +			return;
> 
> 		memset(&cp, 0, sizeof(cp));
> 
> @@ -891,6 +899,21 @@ static void hci_req_directed_advertising(struct hci_request *req,
> 
> 		hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
> 
> +		if (own_addr_type == ADDR_LE_DEV_RANDOM &&
> +		    bacmp(&random_addr, BDADDR_ANY) &&
> +		    bacmp(&random_addr, &hdev->random_addr)) {
> +			struct hci_cp_le_set_adv_set_rand_addr cp;
> +
> +			memset(&cp, 0, sizeof(cp));
> +
> +			cp.handle = 0;
> +			bacpy(&cp.bdaddr, &random_addr);
> +
> +			hci_req_add(req,
> +				    HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
> +				    sizeof(cp), &cp);
> +		}
> +
> 		__hci_req_enable_ext_advertising(req);
> 	} else {
> 		struct hci_cp_le_set_adv_param cp;
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index e703880..dfb2a82 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1061,6 +1061,26 @@ static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
> 	hdev->le_tx_def_phys = cp->tx_phys;
> 	hdev->le_rx_def_phys = cp->rx_phys;
> 
> +        hci_dev_unlock(hdev);

We have some whitespace damage here.

> +}
> +
> +static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
> +                                              struct sk_buff *skb)
> +{
> +        __u8 status = *((__u8 *) skb->data);
> +        struct hci_cp_le_set_adv_set_rand_addr *cp;
> +
> +	if (status)
> +		return;
> +
> +	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
> +	if (!cp)
> +		return;
> +
> +	hci_dev_lock(hdev);
> +
> +	bacpy(&hdev->random_addr, &cp->bdaddr);

Same as with hdev->adv_tx_power, you can not do that. You need to store these per adv instance. I really like to keep the parts that we used for legacy commands different than others.

> +
> 	hci_dev_unlock(hdev);
> }
> 
> @@ -3272,6 +3292,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
> 		hci_cc_le_set_ext_adv_enable(hdev, skb);
> 		break;
> 
> +	case HCI_OP_LE_SET_ADV_SET_RAND_ADDR:
> +		hci_cc_le_set_adv_set_random_addr(hdev, skb);
> +		break;
> +
> 	default:
> 		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
> 		break;
> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> index 7051c5b..6825a65 100644
> --- a/net/bluetooth/hci_request.c
> +++ b/net/bluetooth/hci_request.c
> @@ -1427,6 +1427,87 @@ static void adv_timeout_expire(struct work_struct *work)
> 	hci_dev_unlock(hdev);
> }
> 
> +int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
> +			   bool use_rpa, u8 *own_addr_type, bdaddr_t *rand_addr)
> +{
> +	int err;
> +
> +	bacpy(rand_addr, BDADDR_ANY);
> +
> +	/* If privacy is enabled use a resolvable private address. If
> +	 * current RPA has expired then generate a new one.
> +	 */
> +	if (use_rpa) {
> +		*own_addr_type = ADDR_LE_DEV_RANDOM;
> +
> +		if (!hci_dev_test_and_clear_flag(hdev, HCI_RPA_EXPIRED) &&
> +		    !bacmp(&hdev->random_addr, &hdev->rpa))
> +			return 0;
> +
> +		err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
> +		if (err < 0) {
> +			BT_ERR("%s failed to generate new RPA", hdev->name);
> +			return err;
> +		}
> +
> +		bacpy(rand_addr, &hdev->rpa);
> +
> +		return 0;
> +	}
> +
> +	/* In case of required privacy without resolvable private address,
> +	 * use an non-resolvable private address. This is useful for active
> +	 * scanning and non-connectable advertising.
> +	 */
> +	if (require_privacy) {
> +		bdaddr_t nrpa;
> +
> +		while (true) {
> +			/* The non-resolvable private address is generated
> +			 * from random six bytes with the two most significant
> +			 * bits cleared.
> +			 */
> +			get_random_bytes(&nrpa, 6);
> +			nrpa.b[5] &= 0x3f;
> +
> +			/* The non-resolvable private address shall not be
> +			 * equal to the public address.
> +			 */
> +			if (bacmp(&hdev->bdaddr, &nrpa))
> +				break;
> +		}
> +
> +		*own_addr_type = ADDR_LE_DEV_RANDOM;
> +		bacpy(rand_addr, &nrpa);
> +
> +		return 0;
> +	}
> +
> +	/* If forcing static address is in use or there is no public
> +	 * address use the static address as random address
> +	 *
> +	 * In case BR/EDR has been disabled on a dual-mode controller
> +	 * and a static address has been configured, then use that
> +	 * address instead of the public BR/EDR address.
> +	 */
> +	if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
> +	    !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
> +	    (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
> +	     bacmp(&hdev->static_addr, BDADDR_ANY))) {
> +		*own_addr_type = ADDR_LE_DEV_RANDOM;
> +		bacpy(rand_addr, &hdev->static_addr);
> +
> +		return 0;
> +	}
> +
> +	/* Neither privacy nor static address is being used so use a
> +	 * public address.
> +	 */
> +	*own_addr_type = ADDR_LE_DEV_PUBLIC;
> +
> +	return 0;
> +}
> +

So I am not convinced that we need all of this. For example we only use this for advertising. So our decision for active scanning is useless.

What I think is best that we actually add rand_addr to the adv instance structure and just calculate what random address we want to use ahead of time and keep it stored in the instance. I mean, we want to rotate the address for each instance independently.

> void __hci_req_clear_ext_adv_sets(struct hci_request *req)
> {
> 	hci_req_add(req, HCI_OP_LE_REMOVE_ADV_SET, 0, NULL);
> @@ -1438,6 +1519,9 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
> 	struct hci_dev *hdev = req->hdev;
> 	bool connectable;
> 	u32 flags;
> +	bdaddr_t random_addr;
> +	u8 own_addr_type;
> +	int err;
> 	/* In ext adv set param interval is 3 octets */
> 	const u8 adv_interval[3] = { 0x00, 0x08, 0x00 };
> 
> @@ -1452,6 +1536,16 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
> 	 if (!is_advertising_allowed(hdev, connectable))
> 		return -EPERM;
> 
> +	/* Set require_privacy to true only when non-connectable
> +	 * advertising is used. In that case it is fine to use a
> +	 * non-resolvable private address.
> +	 */
> +	err = hci_get_random_address(hdev, !connectable,
> +				     adv_use_rpa(hdev, flags),
> +				     &own_addr_type, &random_addr);
> +	if (err < 0)
> +		return err;
> +
> 	memset(&cp, 0, sizeof(cp));
> 
> 	memcpy(cp.min_interval, adv_interval, sizeof(cp.min_interval));
> @@ -1464,7 +1558,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
> 	else
> 		cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);
> 
> -	cp.own_addr_type = BDADDR_LE_PUBLIC;
> +	cp.own_addr_type = own_addr_type;
> 	cp.channel_map = hdev->le_adv_channel_map;
> 	cp.tx_power = 127;
> 	cp.primary_phy = HCI_ADV_PHY_1M;
> @@ -1473,6 +1567,21 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
> 
> 	hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
> 
> +	if (own_addr_type == ADDR_LE_DEV_RANDOM &&
> +	    bacmp(&random_addr, BDADDR_ANY) &&
> +	    bacmp(&random_addr, &hdev->random_addr)) {

This really needs to have to compare it per instance. Which means we might actually track the settings for each adv set. So even while initially we only map all instances to a single adv set, we should still track what the current adv set has in it.

> +		struct hci_cp_le_set_adv_set_rand_addr cp;
> +
> +		memset(&cp, 0, sizeof(cp));
> +
> +		cp.handle = 0;
> +		bacpy(&cp.bdaddr, &random_addr);
> +
> +		hci_req_add(req,
> +			    HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
> +			    sizeof(cp), &cp);
> +	}
> +
> 	return 0;
> }
> 
> diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
> index 2451861..5329faf 100644
> --- a/net/bluetooth/hci_request.h
> +++ b/net/bluetooth/hci_request.h
> @@ -84,6 +84,9 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
> int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
> void __hci_req_enable_ext_advertising(struct hci_request *req);
> void __hci_req_clear_ext_adv_sets(struct hci_request *req);
> +int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
> +			   bool use_rpa, u8 *own_addr_type,
> +			   bdaddr_t *rand_addr);
> 

Regards

Marcel


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

* Re: [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command
  2018-07-14 17:00   ` Marcel Holtmann
@ 2018-07-15  7:56     ` Jaganath K
  2018-07-16 13:08       ` Marcel Holtmann
  0 siblings, 1 reply; 39+ messages in thread
From: Jaganath K @ 2018-07-15  7:56 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,


On Sat, Jul 14, 2018 at 10:30 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Jaganath,
>
>> This commands basically retrieve the supported packet types of
>> BREDR and supported PHYs of the controller.
>>
>> BR_1M_1SLOT, LE_1M_TX and LE_1M_RX would be supported by default.
>> Other PHYs are supported based on the local features.
>>
>> @ MGMT Command: Get PHY Configuration (0x0044) plen 0
>> @ MGMT Event: Command Complete (0x0001) plen 15
>>      Get PHY Configuration (0x0044) plen 12
>>        Status: Success (0x00)
>>        Supported PHYs: 0x7fff
>>          BR 1M 1SLOT
>>          BR 1M 3SLOT
>>          BR 1M 5SLOT
>>          EDR 2M 1SLOT
>>          EDR 2M 3SLOT
>>          EDR 2M 5SLOT
>>          EDR 3M 1SLOT
>>          EDR 3M 3SLOT
>>          EDR 3M 5SLOT
>>          LE 1M TX
>>          LE 1M RX
>>          LE 2M TX
>>          LE 2M RX
>>          LE CODED TX
>>          LE CODED RX
>>        Configurable PHYs: 0x79fe
>>          BR 1M 3SLOT
>>          BR 1M 5SLOT
>>          EDR 2M 1SLOT
>>          EDR 2M 3SLOT
>>          EDR 2M 5SLOT
>>          EDR 3M 1SLOT
>>          EDR 3M 3SLOT
>>          EDR 3M 5SLOT
>>          LE 2M TX
>>          LE 2M RX
>>          LE CODED TX
>>          LE CODED RX
>>        Selected PHYs: 0x07ff
>>          BR 1M 1SLOT
>>          BR 1M 3SLOT
>>          BR 1M 5SLOT
>>          EDR 2M 1SLOT
>>          EDR 2M 3SLOT
>>          EDR 2M 5SLOT
>>          EDR 3M 1SLOT
>>          EDR 3M 3SLOT
>>          EDR 3M 5SLOT
>>          LE 1M TX
>>          LE 1M RX
>>
>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>> ---
>> include/net/bluetooth/hci.h      |  14 ++++
>> include/net/bluetooth/hci_core.h |   4 ++
>> include/net/bluetooth/mgmt.h     |  24 +++++++
>> net/bluetooth/mgmt.c             | 149 +++++++++++++++++++++++++++++++++++++++
>> 4 files changed, 191 insertions(+)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index 664fe1e..89bf800 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -291,6 +291,14 @@ enum {
>> #define HCI_DH3               0x0800
>> #define HCI_DH5               0x8000
>>
>> +/* HCI packet types inverted masks */
>> +#define HCI_2DH1     0x0002
>> +#define HCI_3DH1     0x0004
>> +#define HCI_2DH3     0x0100
>> +#define HCI_3DH3     0x0200
>> +#define HCI_2DH5     0x1000
>> +#define HCI_3DH5     0x2000
>> +
>> #define HCI_HV1               0x0020
>> #define HCI_HV2               0x0040
>> #define HCI_HV3               0x0080
>> @@ -354,6 +362,8 @@ enum {
>> #define LMP_PCONTROL  0x04
>> #define LMP_TRANSPARENT       0x08
>>
>> +#define LMP_EDR_2M           0x02
>> +#define LMP_EDR_3M           0x04
>> #define LMP_RSSI_INQ  0x40
>> #define LMP_ESCO      0x80
>>
>> @@ -361,7 +371,9 @@ enum {
>> #define LMP_EV5               0x02
>> #define LMP_NO_BREDR  0x20
>> #define LMP_LE                0x40
>> +#define LMP_EDR_3SLOT        0x80
>>
>> +#define LMP_EDR_5SLOT        0x01
>> #define LMP_SNIFF_SUBR        0x02
>> #define LMP_PAUSE_ENC 0x04
>> #define LMP_EDR_ESCO_2M       0x20
>> @@ -399,6 +411,8 @@ enum {
>> #define HCI_LE_PING                   0x10
>> #define HCI_LE_DATA_LEN_EXT           0x20
>> #define HCI_LE_EXT_SCAN_POLICY                0x80
>> +#define HCI_LE_PHY_2M                        0x01
>> +#define HCI_LE_PHY_CODED             0x08
>> #define HCI_LE_CHAN_SEL_ALG2          0x40
>
> I see why you used _SET in the previous patch. Maybe it is ok to leave it that way.
>
>>
>> /* Connection modes */
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>> index 71f79df..a64d13f 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -1141,6 +1141,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
>> #define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
>> #define lmp_ext_feat_capable(dev)  ((dev)->features[0][7] & LMP_EXTFEATURES)
>> #define lmp_transp_capable(dev)    ((dev)->features[0][2] & LMP_TRANSPARENT)
>> +#define lmp_edr_2m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_2M)
>> +#define lmp_edr_3m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_3M)
>> +#define lmp_edr_3slot_capable(dev) ((dev)->features[0][4] & LMP_EDR_3SLOT)
>> +#define lmp_edr_5slot_capable(dev) ((dev)->features[0][5] & LMP_EDR_5SLOT)
>
> Lets split the non-mgmt related changes from the mgmt ones into separate patches.
>
>>
>> /* ----- Extended LMP capabilities ----- */
>> #define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_MASTER)
>> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
>> index e7303ee..16dddb1 100644
>> --- a/include/net/bluetooth/mgmt.h
>> +++ b/include/net/bluetooth/mgmt.h
>> @@ -604,6 +604,30 @@ struct mgmt_cp_set_appearance {
>> } __packed;
>> #define MGMT_SET_APPEARANCE_SIZE      2
>>
>> +#define MGMT_OP_GET_PHY_CONFIGURATION        0x0044
>> +#define MGMT_GET_PHY_CONFIGURATION_SIZE              0
>> +struct mgmt_rp_get_phy_confguration {
>> +     __le32  supported_phys;
>> +     __le32  configurable_phys;
>> +     __le32  selected_phys;
>> +} __packed;
>> +
>> +#define MGMT_PHY_BR_1M_1SLOT 0x00000001
>> +#define MGMT_PHY_BR_1M_3SLOT 0x00000002
>> +#define MGMT_PHY_BR_1M_5SLOT 0x00000004
>> +#define MGMT_PHY_EDR_2M_1SLOT        0x00000008
>> +#define MGMT_PHY_EDR_2M_3SLOT        0x00000010
>> +#define MGMT_PHY_EDR_2M_5SLOT        0x00000020
>> +#define MGMT_PHY_EDR_3M_1SLOT        0x00000040
>> +#define MGMT_PHY_EDR_3M_3SLOT        0x00000080
>> +#define MGMT_PHY_EDR_3M_5SLOT        0x00000100
>> +#define MGMT_PHY_LE_1M_TX            0x00000200
>> +#define MGMT_PHY_LE_1M_RX            0x00000400
>> +#define MGMT_PHY_LE_2M_TX            0x00000800
>> +#define MGMT_PHY_LE_2M_RX            0x00001000
>> +#define MGMT_PHY_LE_CODED_TX 0x00002000
>> +#define MGMT_PHY_LE_CODED_RX 0x00004000
>> +
>> #define MGMT_EV_CMD_COMPLETE          0x0001
>> struct mgmt_ev_cmd_complete {
>>       __le16  opcode;
>> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
>> index 8a80d48..4a31d4d 100644
>> --- a/net/bluetooth/mgmt.c
>> +++ b/net/bluetooth/mgmt.c
>> @@ -617,6 +617,126 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev,
>>                                &rp, sizeof(rp));
>> }
>>
>> +static u32 get_supported_phys(struct hci_dev *hdev)
>> +{
>> +     u32 supported_phys = 0;
>> +
>> +     if (lmp_bredr_capable(hdev)) {
>> +             supported_phys |= MGMT_PHY_BR_1M_1SLOT;
>> +
>> +             if (hdev->features[0][0] & LMP_3SLOT)
>> +                     supported_phys |= MGMT_PHY_BR_1M_3SLOT;
>> +
>> +             if (hdev->features[0][0] & LMP_5SLOT)
>> +                     supported_phys |= MGMT_PHY_BR_1M_5SLOT;
>> +
>> +             if (lmp_edr_2m_capable(hdev)) {
>> +                     supported_phys |= MGMT_PHY_EDR_2M_1SLOT;
>> +
>> +                     if (lmp_edr_3slot_capable(hdev))
>> +                             supported_phys |= MGMT_PHY_EDR_2M_3SLOT;
>> +
>> +                     if (lmp_edr_5slot_capable(hdev))
>> +                             supported_phys |= MGMT_PHY_EDR_2M_5SLOT;
>> +
>> +                     if (lmp_edr_3m_capable(hdev)) {
>> +                             supported_phys |= MGMT_PHY_EDR_3M_1SLOT;
>> +
>> +                             if (lmp_edr_3slot_capable(hdev))
>> +                                     supported_phys |= MGMT_PHY_EDR_3M_3SLOT;
>> +
>> +                             if (lmp_edr_5slot_capable(hdev))
>> +                                     supported_phys |= MGMT_PHY_EDR_3M_5SLOT;
>> +                     }
>> +             }
>> +     }
>> +
>> +     if (lmp_le_capable(hdev)) {
>> +             supported_phys |= MGMT_PHY_LE_1M_TX;
>> +             supported_phys |= MGMT_PHY_LE_1M_RX;
>> +
>> +             if (hdev->le_features[1] & HCI_LE_PHY_2M) {
>> +                     supported_phys |= MGMT_PHY_LE_2M_TX;
>> +                     supported_phys |= MGMT_PHY_LE_2M_RX;
>> +             }
>
> Extra empty line here.
>
>> +             if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
>> +                     supported_phys |= MGMT_PHY_LE_CODED_TX;
>> +                     supported_phys |= MGMT_PHY_LE_CODED_RX;
>> +             }
>> +     }
>> +
>> +     return supported_phys;
>> +}
>> +
>> +static u32 get_selected_phys(struct hci_dev *hdev)
>> +{
>> +     u32 selected_phys = 0;
>> +
>> +     if (lmp_bredr_capable(hdev)) {
>> +             selected_phys |= MGMT_PHY_BR_1M_1SLOT;
>> +
>> +             if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
>> +                     selected_phys |= MGMT_PHY_BR_1M_3SLOT;
>> +
>> +             if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
>> +                     selected_phys |= MGMT_PHY_BR_1M_5SLOT;
>> +
>> +             if (lmp_edr_2m_capable(hdev)) {
>> +                     if (!(hdev->pkt_type & HCI_2DH1))
>> +                             selected_phys |= MGMT_PHY_EDR_2M_1SLOT;
>> +
>> +                     if (lmp_edr_3slot_capable(hdev) &&
>> +                             !(hdev->pkt_type & HCI_2DH3))
>
> these need to align according to the netdev coding style.
>
>> +                             selected_phys |= MGMT_PHY_EDR_2M_3SLOT;
>> +
>> +                     if (lmp_edr_5slot_capable(hdev) &&
>> +                             !(hdev->pkt_type & HCI_2DH5))
>> +                             selected_phys |= MGMT_PHY_EDR_2M_5SLOT;
>> +
>> +                     if (lmp_edr_3m_capable(hdev)) {
>> +                             if (!(hdev->pkt_type & HCI_3DH1))
>> +                                     selected_phys |= MGMT_PHY_EDR_3M_1SLOT;
>> +
>> +                             if (lmp_edr_3slot_capable(hdev) &&
>> +                                     !(hdev->pkt_type & HCI_3DH3))
>> +                                     selected_phys |= MGMT_PHY_EDR_3M_3SLOT;
>> +
>> +                             if (lmp_edr_5slot_capable(hdev) &&
>> +                                     !(hdev->pkt_type & HCI_3DH5))
>> +                                     selected_phys |= MGMT_PHY_EDR_3M_5SLOT;
>> +                     }
>> +             }
>> +     }
>> +
>> +     if (lmp_le_capable(hdev)) {
>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
>> +                     selected_phys |= MGMT_PHY_LE_1M_TX;
>> +
>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
>> +                     selected_phys |= MGMT_PHY_LE_1M_RX;
>> +
>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
>> +                     selected_phys |= MGMT_PHY_LE_2M_TX;
>> +
>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
>> +                     selected_phys |= MGMT_PHY_LE_2M_RX;
>> +
>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
>> +                     selected_phys |= MGMT_PHY_LE_CODED_TX;
>> +
>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
>> +                     selected_phys |= MGMT_PHY_LE_CODED_RX;
>> +     }
>> +
>> +     return selected_phys;
>> +}
>> +
>> +static u32 get_configurable_phys(struct hci_dev *hdev)
>> +{
>> +     return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
>> +                     ~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
>
> Here the alignment needs to be also corrected.
>
>> +}
>> +
>> static u32 get_supported_settings(struct hci_dev *hdev)
>> {
>>       u32 settings = 0;
>> @@ -654,6 +774,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
>>           hdev->set_bdaddr)
>>               settings |= MGMT_SETTING_CONFIGURATION;
>>
>> +     if (get_supported_phys(hdev) & ~(MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_LE_1M_TX |
>> +                                     MGMT_PHY_LE_1M_RX))
>
> Same here.
>
>> +             settings |= MGMT_SETTING_PHY_CONFIGURATION;
>> +
>
> Frankly I think that PHY configuration can be unconditionally be listed as supported here. Even on a 4.0 or just a 1.2 device we should hint that PHY configuration is possible.

If a controller supports only BR 1M 1 SLOT and / or only LE 1M then
PHY configuration should not be
set (which is what the check is doing).

>
>>       return settings;
>> }
>>
>> @@ -722,6 +846,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
>>                       settings |= MGMT_SETTING_STATIC_ADDRESS;
>>       }
>>
>> +     if (phys_configured(hdev))
>> +             settings |= MGMT_SETTING_PHY_CONFIGURATION;
>> +
>
> What is this conditional doing? You need to add a comment here explaining when we set configuration flag in current settings and when not.

This checks whether any PHY is deselected in BREDR or selected in LE.
Will add comment.

So basically it will be set in supported settings if any PHYs other
than the basic PHYs is supported
and will set in current settings if any PHYs are configured
(deselected in BREDR or selected in LE).

Thanks,
Jaganath

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

* Re: [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command
  2018-07-14 17:18   ` Marcel Holtmann
@ 2018-07-15  9:36     ` Jaganath K
  2018-07-16 13:14       ` Marcel Holtmann
  0 siblings, 1 reply; 39+ messages in thread
From: Jaganath K @ 2018-07-15  9:36 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,


On Sat, Jul 14, 2018 at 10:48 PM, Marcel Holtmann <marcel@holtmann.org> wro=
te:
> Hi Jaganath,
>
>> This enables user to set phys which will be used in all subsequent
>> connections. Also host will use the same in LE scanning as well.
>>
>> This patch also implements PHY Changed event which will be
>> triggered whenever default PHYs change.
>>
>> This also adds PHY_CONFIGURATION to mgmt settings which set
>> in the supported settings if controller supports 2/3 slot
>> or 2M/#M in BREDR controller and 2M or CODED in case of LE
>> and set in current settings if any of them is selected
>>
>> @ MGMT Command: Set PHY Configuration (0x0045) plen 4
>>        Selected PHYs: 0x7fff
>>          BR 1M 1SLOT
>>          BR 1M 3SLOT
>>          BR 1M 5SLOT
>>          EDR 2M 1SLOT
>>          EDR 2M 3SLOT
>>          EDR 2M 5SLOT
>>          EDR 3M 1SLOT
>>          EDR 3M 3SLOT
>>          EDR 3M 5SLOT
>>          LE 1M TX
>>          LE 1M RX
>>          LE 2M TX
>>          LE 2M RX
>>          LE CODED TX
>>          LE CODED RX
>> < HCI Command: LE Set Default PHY (0x08|0x0031) plen 3
>>        All PHYs preference: 0x00
>>        TX PHYs preference: 0x07
>>          LE 1M
>>          LE 2M
>>          LE Coded
>>        RX PHYs preference: 0x07
>>          LE 1M
>>          LE 2M
>>          LE Coded
>>> HCI Event: Command Complete (0x0e) plen 4
>>      LE Set Default PHY (0x08|0x0031) ncmd 1
>>        Status: Success (0x00)
>> @ MGMT Event: Command Complete (0x0001) plen 3
>>      Set PHY Configuration (0x0045) plen 0
>>        Status: Success (0x00)
>> @ MGMT Event: PHY Configuration Changed (0x0026) plen 4
>>        Selected PHYs: 0x7fff
>>          BR 1M 1SLOT
>>          BR 1M 3SLOT
>>          BR 1M 5SLOT
>>          EDR 2M 1SLOT
>>          EDR 2M 3SLOT
>>          EDR 2M 5SLOT
>>          EDR 3M 1SLOT
>>          EDR 3M 3SLOT
>>          EDR 3M 5SLOT
>>          LE 1M TX
>>          LE 1M RX
>>          LE 2M TX
>>          LE 2M RX
>>          LE CODED TX
>>          LE CODED RX
>>
>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>> ---
>> include/net/bluetooth/hci.h      |   1 +
>> include/net/bluetooth/hci_core.h |   1 +
>> include/net/bluetooth/mgmt.h     |  25 +++++
>> net/bluetooth/hci_core.c         |   4 +
>> net/bluetooth/hci_event.c        |  26 +++++
>> net/bluetooth/hci_sock.c         |   1 +
>> net/bluetooth/mgmt.c             | 221 +++++++++++++++++++++++++++++++++=
++++++
>> 7 files changed, 279 insertions(+)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index 89bf800..d0f7657 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -214,6 +214,7 @@ enum {
>>       HCI_MGMT_DEV_CLASS_EVENTS,
>>       HCI_MGMT_LOCAL_NAME_EVENTS,
>>       HCI_MGMT_OOB_DATA_EVENTS,
>> +     HCI_MGMT_PHY_CHANGED_EVENTS,
>> };
>
> is this really needed? These flags are used for events that are condition=
al. Meaning they are send or not send depending on what mgmt command a give=
n socket has called. Since PHY configuration is new and has now legacy comm=
ands it deprecates, I really wonder what this if for. So you need to explai=
n that and if it is needed, split this out into a separate patch that expla=
ins it.
>
>>
>> /*
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hc=
i_core.h
>> index a64d13f..ab5d494 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -1544,6 +1544,7 @@ void mgmt_advertising_added(struct sock *sk, struc=
t hci_dev *hdev,
>>                           u8 instance);
>> void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
>>                             u8 instance);
>> +int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *s=
kip);
>>
>> u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 laten=
cy,
>>                     u16 to_multiplier);
>> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
>> index 16dddb1..047e98d 100644
>> --- a/include/net/bluetooth/mgmt.h
>> +++ b/include/net/bluetooth/mgmt.h
>> @@ -101,6 +101,7 @@ struct mgmt_rp_read_index_list {
>> #define MGMT_SETTING_PRIVACY          0x00002000
>> #define MGMT_SETTING_CONFIGURATION    0x00004000
>> #define MGMT_SETTING_STATIC_ADDRESS   0x00008000
>> +#define MGMT_SETTING_PHY_CONFIGURATION  0x00010000
>
> You are already using this in patch 02/13 and that makes this patch serie=
s non-bisectable.
>
>>
>> #define MGMT_OP_READ_INFO             0x0004
>> #define MGMT_READ_INFO_SIZE           0
>> @@ -628,6 +629,25 @@ struct mgmt_rp_get_phy_confguration {
>> #define MGMT_PHY_LE_CODED_TX  0x00002000
>> #define MGMT_PHY_LE_CODED_RX  0x00004000
>>
>> +#define MGMT_PHY_BREDR_MASK (MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_BR_1M_3SLO=
T | \
>> +                             MGMT_PHY_BR_1M_5SLOT | MGMT_PHY_EDR_2M_1SL=
OT | \
>> +                             MGMT_PHY_EDR_2M_3SLOT | MGMT_PHY_EDR_2M_5S=
LOT | \
>> +                             MGMT_PHY_EDR_3M_1SLOT | MGMT_PHY_EDR_3M_3S=
LOT | \
>> +                             MGMT_PHY_EDR_3M_5SLOT)
>> +#define MGMT_PHY_LE_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX | \
>> +                             MGMT_PHY_LE_2M_TX | MGMT_PHY_LE_2M_RX | \
>> +                             MGMT_PHY_LE_CODED_TX | MGMT_PHY_LE_CODED_R=
X)
>> +#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
>> +                          MGMT_PHY_LE_CODED_TX)
>> +#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \
>> +                          MGMT_PHY_LE_CODED_RX)
>> +
>> +#define MGMT_OP_SET_PHY_CONFIGURATION        0x0045
>> +#define MGMT_SET_PHY_CONFIGURATION_SIZE              4
>> +struct mgmt_cp_set_phy_confguration {
>> +     __le32  selected_phys;
>> +} __packed;
>
> The _SIZE constant is normally below the data structure. Please follow th=
e existing style.
>
>> +
>> #define MGMT_EV_CMD_COMPLETE          0x0001
>> struct mgmt_ev_cmd_complete {
>>       __le16  opcode;
>> @@ -848,3 +868,8 @@ struct mgmt_ev_ext_info_changed {
>>       __le16  eir_len;
>>       __u8    eir[0];
>> } __packed;
>> +
>> +#define MGMT_EV_PHY_CONFIGURATION_CHANGED    0x0026
>> +struct mgmt_ev_phy_configuration_changed {
>> +     __le32  selected_phys;
>> +} __packed;
>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>> index 432f89f..0d88dc9 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -1924,7 +1924,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *ar=
g)
>>               break;
>>
>>       case HCISETPTYPE:
>> +             if (hdev->pkt_type =3D=3D ((__u16) dr.dev_opt))
>> +                     break;
>> +
>
> What is the extra () doing here? I doubt that is needed.
>
>>               hdev->pkt_type =3D (__u16) dr.dev_opt;
>> +             mgmt_phy_configuration_changed(hdev, NULL);
>>               break;
>
> Also I would do that as a separate patch with a clear commit message that=
 this is for legacy behavior. But now I see why you might need that PHY cha=
nged event flag.
>
> So lets really do that in a separate patch to clearly point out legacy be=
havior and the change needed for handling it. This includes the events flag=
 etc. One question I have is if we care if the event is send all the time o=
r not.
>
> So for a client this is not conflicting information or duplicated informa=
tion coming along. It just means that someone changed the PHY configuration=
. This can happen via ioctl or mgmt and frankly an observer mgmt client wou=
ldn't be able to tell the difference anyway. So maybe this is just overkill=
 with no purpose.

So you mean we dont need the new flag?

>
> Also we might better make mgmt_phy_configuration_changed capable of check=
ing if an event is needed or not. Meaning it should check by itself if some=
thing changed or not. Don't remember how we did this for other functions. S=
o something to look into.
>
>>
>>       case HCISETACLMTU:
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index 6819215..6942315 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -1042,6 +1042,28 @@ static void hci_cc_le_set_random_addr(struct hci_=
dev *hdev, struct sk_buff *skb)
>>       hci_dev_unlock(hdev);
>> }
>>
>> +static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_b=
uff *skb)
>> +{
>> +     __u8 status =3D *((__u8 *) skb->data);
>> +     struct hci_cp_le_set_default_phy *cp;
>> +
>> +     BT_DBG("%s status 0x%2.2x", hdev->name, status);
>> +
>> +     if (status)
>> +             return;
>> +
>> +     cp =3D hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
>> +     if (!cp)
>> +             return;
>> +
>> +     hci_dev_lock(hdev);
>> +
>> +     hdev->le_tx_def_phys =3D cp->tx_phys;
>> +     hdev->le_rx_def_phys =3D cp->rx_phys;
>> +
>> +     hci_dev_unlock(hdev);
>> +}
>> +
>> static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buf=
f *skb)
>> {
>>       __u8 *sent, status =3D *((__u8 *) skb->data);
>> @@ -3163,6 +3185,10 @@ static void hci_cmd_complete_evt(struct hci_dev *=
hdev, struct sk_buff *skb,
>>               hci_cc_le_set_ext_scan_enable(hdev, skb);
>>               break;
>>
>> +     case HCI_OP_LE_SET_DEFAULT_PHY:
>> +             hci_cc_le_set_default_phy(hdev, skb);
>> +             break;
>> +
>>       default:
>>               BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
>>               break;
>> diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
>> index 1506e16..476916c 100644
>> --- a/net/bluetooth/hci_sock.c
>> +++ b/net/bluetooth/hci_sock.c
>> @@ -1328,6 +1328,7 @@ static int hci_sock_bind(struct socket *sock, stru=
ct sockaddr *addr,
>>                       hci_sock_set_flag(sk, HCI_MGMT_SETTING_EVENTS);
>>                       hci_sock_set_flag(sk, HCI_MGMT_DEV_CLASS_EVENTS);
>>                       hci_sock_set_flag(sk, HCI_MGMT_LOCAL_NAME_EVENTS);
>> +                     hci_sock_set_flag(sk, HCI_MGMT_PHY_CHANGED_EVENTS)=
;
>>               }
>>               break;
>>       }
>> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
>> index 4a31d4d..1c2ed42 100644
>> --- a/net/bluetooth/mgmt.c
>> +++ b/net/bluetooth/mgmt.c
>> @@ -737,6 +737,23 @@ static u32 get_configurable_phys(struct hci_dev *hd=
ev)
>>                       ~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
>> }
>>
>> +static bool phys_configured(struct hci_dev *hdev)
>> +{
>> +     u32 selected_phys =3D get_selected_phys(hdev);
>> +     u32 supported_phys =3D get_supported_phys(hdev);
>> +
>> +     /* If any of BREDR supported PHYs are deselected or
>> +      *  LE PHYs other than 1M are selected
>
> You have extra spaces in the front.
>
>> +      */
>> +     if (((supported_phys & MGMT_PHY_BREDR_MASK) !=3D
>> +              (selected_phys & MGMT_PHY_BREDR_MASK)) ||
>> +             ((selected_phys & MGMT_PHY_LE_MASK) &
>> +               ~(MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX)))
>
> This alignment is not okay. Go over the character per line limit here if =
needed.
>
> One question though, why are making an exception for LE_1M here?
>

LE is supported will mean that LE_!M is supported and also cannot be
configured (deselected).

>> +             return true;
>> +
>> +     return false;
>> +}
>> +
>> static u32 get_supported_settings(struct hci_dev *hdev)
>> {
>>       u32 settings =3D 0;
>> @@ -3332,6 +3349,209 @@ static int get_phy_configuration(struct sock *sk=
, struct hci_dev *hdev,
>>                                &rp, sizeof(rp));
>> }
>>
>> +int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *s=
kip)
>> +{
>> +     struct mgmt_ev_phy_configuration_changed ev;
>> +
>> +     memset(&ev, 0, sizeof(ev));
>> +
>> +     ev.selected_phys =3D cpu_to_le32(get_selected_phys(hdev));
>> +
>> +     return mgmt_limited_event(MGMT_EV_PHY_CONFIGURATION_CHANGED, hdev,=
 &ev,
>> +                               sizeof(ev), HCI_MGMT_PHY_CHANGED_EVENTS,
>> +                               skip);
>> +}
>> +
>> +static void set_default_phy_complete(struct hci_dev *hdev, u8 status,
>> +                                  u16 opcode, struct sk_buff *skb)
>> +{
>> +     struct mgmt_cp_set_phy_confguration *cp;
>> +     struct mgmt_pending_cmd *cmd;
>> +
>> +     BT_DBG("status 0x%02x", status);
>> +
>> +     hci_dev_lock(hdev);
>> +
>> +     cmd =3D pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev);
>> +     if (!cmd)
>> +             goto unlock;
>> +
>> +     cp =3D cmd->param;
>> +
>> +     if (status) {
>> +             mgmt_cmd_status(cmd->sk, hdev->id,
>> +                             MGMT_OP_SET_PHY_CONFIGURATION,
>> +                             mgmt_status(status));
>> +     } else {
>> +             mgmt_cmd_complete(cmd->sk, hdev->id,
>> +                               MGMT_OP_SET_PHY_CONFIGURATION, 0,
>> +                               NULL, 0);
>> +
>> +             mgmt_phy_configuration_changed(hdev, cmd->sk);
>> +             new_settings(hdev, cmd->sk);
>
> This new_settings we really need to discuss and document its behavior.

As per our initial discussion, NewSettings will have PHY Configuration bit =
set
if any PHYs other than 1M is selected. I have extended it to BREDR wherein =
it
will be set if any of the PHYs are deselected.

Thanks,
Jaganath

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

* Re: [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types
  2018-07-14 17:28   ` Marcel Holtmann
@ 2018-07-15  9:52     ` Jaganath K
  2018-07-16 13:09       ` Marcel Holtmann
  0 siblings, 1 reply; 39+ messages in thread
From: Jaganath K @ 2018-07-15  9:52 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,

On Sat, Jul 14, 2018 at 10:58 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Jaganath,
>
>> This patch defines the extended ADV types and handle it in ADV report.
>>
>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>> ---
>> include/net/bluetooth/hci.h |  8 ++++++++
>> net/bluetooth/hci_event.c   | 49 +++++++++++++++++++++++++++++++--------------
>> 2 files changed, 42 insertions(+), 15 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index 3584632..fcd1d57 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -1977,6 +1977,14 @@ struct hci_ev_le_conn_complete {
>> #define LE_LEGACY_SCAN_RSP_ADV                0x001b
>> #define LE_LEGACY_SCAN_RSP_ADV_SCAN   0x001a
>>
>> +/* Extended Advertising event types */
>> +#define LE_EXT_ADV_NON_CONN_IND              0x0000
>> +#define LE_EXT_ADV_CONN_IND          0x0001
>> +#define LE_EXT_ADV_SCAN_IND          0x0002
>> +#define LE_EXT_ADV_DIRECT_IND                0x0004
>> +#define LE_EXT_ADV_SCAN_RSP          0x0008
>> +#define LE_EXT_ADV_LEGACY_PDU                0x0010
>> +
>> #define ADDR_LE_DEV_PUBLIC    0x00
>> #define ADDR_LE_DEV_RANDOM    0x01
>>
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index 6942315..027abe6 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -5137,20 +5137,39 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
>>       hci_dev_unlock(hdev);
>> }
>>
>> -static u8 convert_legacy_evt_type(u16 evt_type)
>> -{
>> -     switch (evt_type) {
>> -     case LE_LEGACY_ADV_IND:
>> -             return LE_ADV_IND;
>> -     case LE_LEGACY_ADV_DIRECT_IND:
>> -             return LE_ADV_DIRECT_IND;
>> -     case LE_LEGACY_ADV_SCAN_IND:
>> -             return LE_ADV_SCAN_IND;
>> -     case LE_LEGACY_NONCONN_IND:
>> -             return LE_ADV_NONCONN_IND;
>> -     case LE_LEGACY_SCAN_RSP_ADV:
>> -     case LE_LEGACY_SCAN_RSP_ADV_SCAN:
>> -             return LE_ADV_SCAN_RSP;
>> +static u8 convert_ext_evt_type(u16 evt_type)
>> +{
>> +     if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
>> +             switch (evt_type) {
>> +             case LE_LEGACY_ADV_IND:
>> +                     return LE_ADV_IND;
>> +             case LE_LEGACY_ADV_DIRECT_IND:
>> +                     return LE_ADV_DIRECT_IND;
>> +             case LE_LEGACY_ADV_SCAN_IND:
>> +                     return LE_ADV_SCAN_IND;
>> +             case LE_LEGACY_NONCONN_IND:
>> +                     return LE_ADV_NONCONN_IND;
>> +             case LE_LEGACY_SCAN_RSP_ADV:
>> +             case LE_LEGACY_SCAN_RSP_ADV_SCAN:
>> +                     return LE_ADV_SCAN_RSP;
>> +             }
>
> I would do a return here since only the legacy part is special.
>
>> +     } else {
>> +             if (evt_type & LE_EXT_ADV_CONN_IND) {
>> +                     if (evt_type & LE_EXT_ADV_DIRECT_IND)
>> +                             return LE_ADV_DIRECT_IND;
>> +
>> +                     return LE_ADV_IND;
>> +             }
>> +
>> +             if (evt_type & LE_EXT_ADV_SCAN_RSP)
>> +                     return LE_ADV_SCAN_RSP;
>> +
>> +             if (evt_type & LE_EXT_ADV_SCAN_IND)
>> +                     return LE_ADV_SCAN_IND;
>> +
>> +             if (evt_type == LE_EXT_ADV_NON_CONN_IND ||
>> +                 evt_type & LE_EXT_ADV_DIRECT_IND)
>> +                     return LE_ADV_NONCONN_IND;
>
> Why do we have one == match here and the rest are bit checks.
>
>>       }
>>
>>       BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
>> @@ -5172,7 +5191,7 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
>>               u16 evt_type;
>>
>>               evt_type = __le16_to_cpu(ev->evt_type);
>> -             legacy_evt_type = convert_legacy_evt_type(evt_type);
>> +             legacy_evt_type = convert_ext_evt_type(evt_type);
>
> So ext_evt_type_to_legacy might be a better function name here.
>
>>               if (legacy_evt_type != LE_ADV_INVALID) {
>
> I might have asked this before, when are we reaching _INVALID here?
>

It will be hit in case of an unknown advertising pkt type.

Thanks,
Jaganath

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

* Re: [PATCH v4 07/13] Bluetooth: Read no of adv sets during init
  2018-07-14 17:32   ` Marcel Holtmann
@ 2018-07-16  6:27     ` Jaganath K
  2018-07-16 13:18       ` Marcel Holtmann
  0 siblings, 1 reply; 39+ messages in thread
From: Jaganath K @ 2018-07-16  6:27 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,

On Sat, Jul 14, 2018 at 11:02 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Jaganath,
>
>> This patch reads the number of advertising sets in the controller
>> during init and save it in hdev.
>>
>> This also checks ext adv support before send Read Adv TX Power
>> since legacy and extended Adv commands should not be mixed.
>>
>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>> ---
>> include/net/bluetooth/hci.h      |  7 +++++++
>> include/net/bluetooth/hci_core.h |  4 ++++
>> net/bluetooth/hci_core.c         | 12 ++++++++++--
>> net/bluetooth/hci_event.c        | 18 ++++++++++++++++++
>> 4 files changed, 39 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index fcd1d57..e584863 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -411,6 +411,7 @@ enum {
>> #define HCI_LE_SLAVE_FEATURES         0x08
>> #define HCI_LE_PING                   0x10
>> #define HCI_LE_DATA_LEN_EXT           0x20
>> +#define HCI_LE_EXT_ADV                       0x10
>> #define HCI_LE_EXT_SCAN_POLICY                0x80
>> #define HCI_LE_PHY_2M                 0x01
>> #define HCI_LE_PHY_CODED              0x08
>> @@ -1580,6 +1581,12 @@ struct hci_cp_le_ext_conn_param {
>>       __le16 max_ce_len;
>> } __packed;
>>
>> +#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS        0x203b
>> +struct hci_rp_le_read_num_supported_adv_sets {
>> +     __u8  status;
>> +     __u8  num_of_sets;
>> +} __packed;
>> +
>> /* ---- HCI Events ---- */
>> #define HCI_EV_INQUIRY_COMPLETE               0x01
>>
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>> index 33aab89e..e845ca6 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -222,6 +222,7 @@ struct hci_dev {
>>       __u8            le_features[8];
>>       __u8            le_white_list_size;
>>       __u8            le_resolv_list_size;
>> +     __u8            le_no_of_adv_sets;
>
> I think our style was to use _num instead of _no. See num_iac for example.
>
>>       __u8            le_states[8];
>>       __u8            commands[64];
>>       __u8            hci_ver;
>> @@ -1180,6 +1181,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
>> /* Use ext create connection if command is supported */
>> #define use_ext_conn(dev) ((dev)->commands[37] & 0x80)
>>
>> +/* Extended advertising support */
>> +#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
>> +
>> /* ----- HCI protocols ----- */
>> #define HCI_PROTO_DEFER             0x01
>>
>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>> index 0d88dc9..b423587 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -715,8 +715,10 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
>>               hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
>>                           events);
>>
>> -             if (hdev->commands[25] & 0x40) {
>> -                     /* Read LE Advertising Channel TX Power */
>> +             if ((hdev->commands[25] & 0x40) && !ext_adv_capable(hdev)) {
>> +                     /* Read LE Advertising Channel TX Power only if
>> +                      * extended advertising is not supported
>> +                      */
>>                       hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
>>               }
>
> Why? I prefer that we read the adv TX power always. Even if we are not using it, it is good to have it in the traces.

Mixing of legacy and extended commands is forbidden as per HCI TS spec
Please see  "HCI/GEV/BV-02-C [Disallow Mixing Legacy and Extended Advertising
Commands]"

Thanks,
Jaganath

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

* Re: [PATCH v4 08/13] Bluetooth: Impmlement extended adv enable
  2018-07-14 18:38   ` Marcel Holtmann
@ 2018-07-16  8:12     ` Jaganath K
  0 siblings, 0 replies; 39+ messages in thread
From: Jaganath K @ 2018-07-16  8:12 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,

On Sun, Jul 15, 2018 at 12:08 AM, Marcel Holtmann <marcel@holtmann.org> wro=
te:
> Hi Jaganath,
>
>> This patch basically replaces legacy adv with extended adv
>> based on the controller support. Currently there is no
>> design change. ie only one adv set will be enabled at a time.
>>
>> < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen=
 25
>>        Handle: 0x00
>>        Properties: 0x0010
>>          Use legacy advertising PDUs: ADV_NONCONN_IND
>>        Min advertising interval: 1280.000 msec (0x0800)
>>        Max advertising interval: 1280.000 msec (0x0800)
>>        Channel map: 37, 38, 39 (0x07)
>>        Own address type: Random (0x01)
>>        Peer address type: Public (0x00)
>>        Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
>>        Filter policy: Allow Scan Request from Any, Allow Connect Request=
 from Any (0x00)
>>        TX power: 127 dbm (0x7f)
>>        Primary PHY: LE 1M (0x01)
>>        Secondary max skip: 0x00
>>        Secondary PHY: LE 1M (0x01)
>>        SID: 0x00
>>        Scan request notifications: Disabled (0x00)
>>> HCI Event: Command Complete (0x0e) plen 5
>>      LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1
>>        Status: Success (0x00)
>>        TX power (selected): 7 dbm (0x07)
>> < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6
>>        Extended advertising: Enabled (0x01)
>>        Number of sets: 1 (0x01)
>>        Entry 0
>>          Handle: 0x00
>>          Duration: 0 ms (0x00)
>>          Max ext adv events: 0
>>> HCI Event: Command Complete (0x0e) plen 4
>>      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
>>        Status: Success (0x00)
>>
>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>> ---
>> include/net/bluetooth/hci.h |  39 ++++++++++++
>> net/bluetooth/hci_event.c   |  63 +++++++++++++++++++
>> net/bluetooth/hci_request.c | 144 ++++++++++++++++++++++++++++++++++++++=
++----
>> net/bluetooth/hci_request.h |   3 +
>> net/bluetooth/mgmt.c        |  19 ++++--
>> 5 files changed, 251 insertions(+), 17 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index e584863..c0c542d 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -1587,6 +1587,45 @@ struct hci_rp_le_read_num_supported_adv_sets {
>>       __u8  num_of_sets;
>> } __packed;
>>
>> +#define HCI_OP_LE_SET_EXT_ADV_PARAMS                 0x2036
>> +struct hci_cp_le_set_ext_adv_params {
>> +     __u8  handle;
>> +     __le16 evt_properties;
>> +     __u8  min_interval[3];
>> +     __u8  max_interval[3];
>> +     __u8  channel_map;
>> +     __u8  own_addr_type;
>> +     __u8  peer_addr_type;
>> +     bdaddr_t  peer_addr;
>> +     __u8  filter_policy;
>> +     __u8  tx_power;
>> +     __u8  primary_phy;
>> +     __u8  secondary_max_skip;
>> +     __u8  secondary_phy;
>> +     __u8  sid;
>> +     __u8  notif_enable;
>> +} __packed;
>
> please do proper alignment here and follow the style we currently have in=
 hci.h.
>
>> +
>> +#define HCI_ADV_PHY_1M               0X01
>> +
>> +struct hci_rp_le_set_ext_adv_params {
>> +     __u8  status;
>> +     __u8  tx_power;
>> +} __attribute__ ((packed));
>> +
>> +#define HCI_OP_LE_SET_EXT_ADV_ENABLE                 0x2039
>> +struct hci_cp_le_set_ext_adv_enable {
>> +     __u8  enable;
>> +     __u8  num_of_sets;
>> +     __u8  data[0];
>> +} __packed;
>> +
>> +struct hci_cp_ext_adv_set {
>> +     __u8  handle;
>> +     __le16 duration;
>> +     __u8  max_events;
>> +} __packed;
>> +
>> /* ---- HCI Events ---- */
>> #define HCI_EV_INQUIRY_COMPLETE               0x01
>>
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index 90e7235..e17002f 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -1099,6 +1099,41 @@ static void hci_cc_le_set_adv_enable(struct hci_d=
ev *hdev, struct sk_buff *skb)
>>       hci_dev_unlock(hdev);
>> }
>>
>> +static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
>> +                                      struct sk_buff *skb)
>> +{
>> +     struct hci_cp_le_set_ext_adv_enable *cp;
>> +     struct hci_cp_ext_adv_set *adv_set;
>> +     __u8 status =3D *((__u8 *) skb->data);
>> +
>> +     BT_DBG("%s status 0x%2.2x", hdev->name, status);
>> +
>> +     if (status)
>> +             return;
>> +
>> +     cp =3D hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
>> +     if (!cp)
>> +             return;
>> +
>> +     adv_set =3D (void *) cp->data;
>> +
>> +     hci_dev_lock(hdev);
>> +
>> +     if (cp->enable) {
>> +             struct hci_conn *conn;
>> +
>> +             hci_dev_set_flag(hdev, HCI_LE_ADV);
>> +
>> +             conn =3D hci_lookup_le_connect(hdev);
>> +             if (conn)
>> +                     queue_delayed_work(hdev->workqueue,
>> +                                        &conn->le_conn_timeout,
>> +                                        conn->conn_timeout);
>> +     }
>> +
>> +     hci_dev_unlock(hdev);
>> +}
>> +
>> static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buf=
f *skb)
>> {
>>       struct hci_cp_le_set_scan_param *cp;
>> @@ -1486,6 +1521,26 @@ static void hci_cc_set_adv_param(struct hci_dev *=
hdev, struct sk_buff *skb)
>>       hci_dev_unlock(hdev);
>> }
>>
>> +static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_bu=
ff *skb)
>> +{
>> +     struct hci_rp_le_set_ext_adv_params *rp =3D (void *) skb->data;
>> +     struct hci_cp_le_set_ext_adv_params *cp;
>> +
>> +     BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
>> +
>> +     if (rp->status)
>> +             return;
>> +
>> +     cp =3D hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
>> +     if (!cp)
>> +             return;
>> +
>> +     hci_dev_lock(hdev);
>> +     hdev->adv_addr_type =3D cp->own_addr_type;
>> +     hdev->adv_tx_power =3D rp->tx_power;
>
> Don't do this. The adv_tx_power is meant for the default adv TX power of =
the controller. This can not be overwritten. Leave this alone for now. I re=
alize that you want this to support the TX power data type, but that needs =
to be stored in the adv instance then. And then used from there.
>
> So create a pre-change that has the tx_power information in the adv insta=
nce. And on instance populate it using hdev->adv_tx_power. Use that also fo=
r ext adv parameters and when the parameter setting comes back then update =
the value with the controller chosen TX power. So that adv data has the cor=
rect value in there.
>

I will add tx_power in the instance and initialize with INVALID as no point
in using hdev->adv_tx_power since it will be INVALID anyway.

> Please note that in case of not using legacy advertising and actually tra=
nsmitting TX power via ext adv, then we need to make sure it is not include=
d in the adv data.
>

I did not get the comment "actually transmitting TX power via ext adv".
As far as I understood, in ext adv, tx_power will be always valid which
is returned from set_param and if it is set in the flags by user it has to =
be
always included in adv data.

>> +     hci_dev_unlock(hdev);
>> +}
>> +
>> static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
>> {
>>       struct hci_rp_read_rssi *rp =3D (void *) skb->data;
>> @@ -3207,6 +3262,14 @@ static void hci_cmd_complete_evt(struct hci_dev *=
hdev, struct sk_buff *skb,
>>               hci_cc_le_read_num_adv_sets(hdev, skb);
>>               break;
>>
>> +     case HCI_OP_LE_SET_EXT_ADV_PARAMS:
>> +             hci_cc_set_ext_adv_param(hdev, skb);
>> +             break;
>> +
>> +     case HCI_OP_LE_SET_EXT_ADV_ENABLE:
>> +             hci_cc_le_set_ext_adv_enable(hdev, skb);
>> +             break;
>> +
>>       default:
>>               BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
>>               break;
>> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
>> index 7f5950e..a2091b5 100644
>> --- a/net/bluetooth/hci_request.c
>> +++ b/net/bluetooth/hci_request.c
>> @@ -894,6 +894,24 @@ void hci_req_add_le_passive_scan(struct hci_request=
 *req)
>>                          hdev->le_scan_window, own_addr_type, filter_pol=
icy);
>> }
>>
>> +static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instan=
ce)
>> +{
>> +     struct adv_info *adv_instance;
>> +
>> +     /* Ignore instance 0 */
>> +     if (instance =3D=3D 0x00)
>> +             return 0;
>> +
>> +     adv_instance =3D hci_find_adv_instance(hdev, instance);
>> +     if (!adv_instance)
>> +             return 0;
>> +
>> +     /* TODO: Take into account the "appearance" and "local-name" flags=
 here.
>> +      * These are currently being ignored as they are not supported.
>> +      */
>> +     return adv_instance->scan_rsp_len;
>> +}
>> +
>> static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
>> {
>>       u8 instance =3D hdev->cur_adv_instance;
>> @@ -1303,9 +1321,13 @@ void hci_req_reenable_advertising(struct hci_dev =
*hdev)
>>               __hci_req_schedule_adv_instance(&req, hdev->cur_adv_instan=
ce,
>>                                               true);
>>       } else {
>> -             __hci_req_update_adv_data(&req, 0x00);
>> -             __hci_req_update_scan_rsp_data(&req, 0x00);
>> -             __hci_req_enable_advertising(&req);
>> +             if (ext_adv_capable(hdev)) {
>> +                     __hci_req_start_ext_adv(&req, 0x00);
>> +             } else {
>> +                     __hci_req_update_adv_data(&req, 0x00);
>> +                     __hci_req_update_scan_rsp_data(&req, 0x00);
>> +                     __hci_req_enable_advertising(&req);
>> +             }
>>       }
>>
>>       hci_req_run(&req, adv_enable_complete);
>> @@ -1342,6 +1364,88 @@ static void adv_timeout_expire(struct work_struct=
 *work)
>>       hci_dev_unlock(hdev);
>> }
>>
>> +static int __hci_req_setup_ext_adv_instance(struct hci_request *req,
>> +                                         u8 instance)
>> +{
>> +     struct hci_cp_le_set_ext_adv_params cp;
>> +     struct hci_dev *hdev =3D req->hdev;
>> +     bool connectable;
>> +     u32 flags;
>> +     /* In ext adv set param interval is 3 octets */
>> +     const u8 adv_interval[3] =3D { 0x00, 0x08, 0x00 };
>> +
>> +     flags =3D get_adv_instance_flags(hdev, instance);
>> +
>> +     /* If the "connectable" instance flag was not set, then choose bet=
ween
>> +      * ADV_IND and ADV_NONCONN_IND based on the global connectable set=
ting.
>> +      */
>> +     connectable =3D (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
>> +                   mgmt_get_connectable(hdev);
>> +
>> +      if (!is_advertising_allowed(hdev, connectable))
>> +             return -EPERM;
>> +
>> +     memset(&cp, 0, sizeof(cp));
>> +
>> +     memcpy(cp.min_interval, adv_interval, sizeof(cp.min_interval));
>> +     memcpy(cp.max_interval, adv_interval, sizeof(cp.max_interval));
>> +
>> +     if (connectable)
>> +             cp.evt_properties =3D cpu_to_le16(LE_LEGACY_ADV_IND);
>> +     else if (get_adv_instance_scan_rsp_len(hdev, instance))
>> +             cp.evt_properties =3D cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);
>> +     else
>> +             cp.evt_properties =3D cpu_to_le16(LE_LEGACY_NONCONN_IND);
>> +
>> +     cp.own_addr_type =3D BDADDR_LE_PUBLIC;
>> +     cp.channel_map =3D hdev->le_adv_channel_map;
>> +     cp.tx_power =3D 127;
>> +     cp.primary_phy =3D HCI_ADV_PHY_1M;
>> +     cp.secondary_phy =3D HCI_ADV_PHY_1M;
>> +     cp.handle =3D 0;
>> +
>> +     hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
>> +
>> +     return 0;
>> +}
>> +
>> +void __hci_req_enable_ext_advertising(struct hci_request *req)
>> +{
>> +     struct hci_cp_le_set_ext_adv_enable *cp;
>> +     struct hci_cp_ext_adv_set *adv_set;
>> +     u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
>> +
>> +     cp =3D (void *) data;
>> +     adv_set =3D (void *) cp->data;
>> +
>> +     memset(cp, 0, sizeof(*cp));
>> +
>> +     cp->enable =3D 0x01;
>> +     cp->num_of_sets =3D 0x01;
>> +
>> +     memset(adv_set, 0, sizeof(*adv_set));
>> +
>> +     adv_set->handle =3D 0;
>> +
>> +     hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE,
>> +                 sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
>> +                 data);
>> +}
>> +
>> +int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
>> +{
>> +     struct hci_dev *hdev =3D req->hdev;
>> +     int err;
>> +
>> +     err =3D __hci_req_setup_ext_adv_instance(req, instance);
>> +     if (err < 0)
>> +             return err;
>> +
>> +     __hci_req_enable_ext_advertising(req);
>> +
>> +     return 0;
>> +}
>> +
>> int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance=
,
>>                                   bool force)
>> {
>> @@ -1395,9 +1499,13 @@ int __hci_req_schedule_adv_instance(struct hci_re=
quest *req, u8 instance,
>>               return 0;
>>
>>       hdev->cur_adv_instance =3D instance;
>> -     __hci_req_update_adv_data(req, instance);
>> -     __hci_req_update_scan_rsp_data(req, instance);
>> -     __hci_req_enable_advertising(req);
>> +     if (ext_adv_capable(hdev)) {
>> +             __hci_req_start_ext_adv(req, instance);
>> +     } else {
>> +             __hci_req_update_adv_data(req, instance);
>> +             __hci_req_update_scan_rsp_data(req, instance);
>> +             __hci_req_enable_advertising(req);
>> +     }
>>
>>       return 0;
>> }
>> @@ -1668,8 +1776,12 @@ static int connectable_update(struct hci_request =
*req, unsigned long opt)
>>
>>       /* Update the advertising parameters if necessary */
>>       if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
>> -         !list_empty(&hdev->adv_instances))
>> -             __hci_req_enable_advertising(req);
>> +         !list_empty(&hdev->adv_instances)) {
>> +             if (ext_adv_capable(hdev))
>> +                     __hci_req_start_ext_adv(req, hdev->cur_adv_instanc=
e);
>> +             else
>> +                     __hci_req_enable_advertising(req);
>> +     }
>>
>>       __hci_update_background_scan(req);
>>
>> @@ -1778,8 +1890,12 @@ static int discoverable_update(struct hci_request=
 *req, unsigned long opt)
>>               /* Discoverable mode affects the local advertising
>>                * address in limited privacy mode.
>>                */
>> -             if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY))
>> -                     __hci_req_enable_advertising(req);
>> +             if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) {
>> +                     if (ext_adv_capable(hdev))
>> +                             __hci_req_start_ext_adv(req, 0x00);
>> +                     else
>> +                             __hci_req_enable_advertising(req);
>> +             }
>>       }
>>
>>       hci_dev_unlock(hdev);
>> @@ -2375,8 +2491,12 @@ static int powered_update_hci(struct hci_request =
*req, unsigned long opt)
>>                       __hci_req_update_adv_data(req, 0x00);
>>                       __hci_req_update_scan_rsp_data(req, 0x00);
>>
>> -                     if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
>> -                             __hci_req_enable_advertising(req);
>> +                     if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
>> +                             if (ext_adv_capable(hdev))
>> +                                     __hci_req_start_ext_adv(req, 0x00)=
;
>> +                             else
>> +                                     __hci_req_enable_advertising(req);
>> +                     }
>>               } else if (!list_empty(&hdev->adv_instances)) {
>>                       struct adv_info *adv_instance;
>>
>> diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
>> index 702beb1..9b8c74d 100644
>> --- a/net/bluetooth/hci_request.h
>> +++ b/net/bluetooth/hci_request.h
>> @@ -80,6 +80,9 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, =
struct sock *sk,
>>                               struct hci_request *req, u8 instance,
>>                               bool force);
>>
>> +int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
>> +void __hci_req_enable_ext_advertising(struct hci_request *req);
>> +
>> void __hci_req_update_class(struct hci_request *req);
>>
>> /* Returns true if HCI commands were queued */
>> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
>> index 1c2ed42..22997f8 100644
>> --- a/net/bluetooth/mgmt.c
>> +++ b/net/bluetooth/mgmt.c
>> @@ -961,7 +961,10 @@ static void rpa_expired(struct work_struct *work)
>>        * function.
>>        */
>>       hci_req_init(&req, hdev);
>> -     __hci_req_enable_advertising(&req);
>> +     if (ext_adv_capable(hdev))
>> +             __hci_req_start_ext_adv(&req, hdev->cur_adv_instance);
>> +     elsey
>> +             __hci_req_enable_advertising(&req);
>>       hci_req_run(&req, NULL);
>> }
>>
>> @@ -4405,9 +4408,14 @@ static int set_advertising(struct sock *sk, struc=
t hci_dev *hdev, void *data,
>>                * HCI_ADVERTISING flag is not yet set.
>>                */
>>               hdev->cur_adv_instance =3D 0x00;
>> -             __hci_req_update_adv_data(&req, 0x00);
>> -             __hci_req_update_scan_rsp_data(&req, 0x00);
>> -             __hci_req_enable_advertising(&req);
>> +
>> +             if (ext_adv_capable(hdev)) {
>> +                     __hci_req_start_ext_adv(&req, 0x00);
>> +             } else {
>> +                     __hci_req_update_adv_data(&req, 0x00);
>> +                     __hci_req_update_scan_rsp_data(&req, 0x00);
>> +                     __hci_req_enable_advertising(&req);
>> +             }
>>       } else {
>>               __hci_req_disable_advertising(&req);
>>       }
>> @@ -6335,7 +6343,8 @@ static u32 get_supported_adv_flags(struct hci_dev =
*hdev)
>>       flags |=3D MGMT_ADV_FLAG_APPEARANCE;
>>       flags |=3D MGMT_ADV_FLAG_LOCAL_NAME;
>>
>> -     if (hdev->adv_tx_power !=3D HCI_TX_POWER_INVALID)
>> +     if ((hdev->adv_tx_power !=3D HCI_TX_POWER_INVALID) ||
>> +         ext_adv_capable(hdev))
>>               flags |=3D MGMT_ADV_FLAG_TX_POWER;
>
> See comments above on how this needs to be handled differently.

As mentioned above, in ext adv, tx_power will be always valid, so this
code looks fine for me. Plz let me know if i am missing something.

Thanks,
Jaganath

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

* Re: [PATCH v4 10/13] Bluetooth: Implement disable and removal of adv instance
  2018-07-14 18:50   ` Marcel Holtmann
@ 2018-07-16  8:21     ` Jaganath K
  0 siblings, 0 replies; 39+ messages in thread
From: Jaganath K @ 2018-07-16  8:21 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,

On Sun, Jul 15, 2018 at 12:20 AM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Jaganath,
>
>> If ext adv is enabled then use ext adv to disable as well.
>> Also remove the adv set during LE disable.
>>
>> < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 2
>>        Extended advertising: Disabled (0x00)
>>        Number of sets: Disable all sets (0x00)
>>> HCI Event: Command Complete (0x0e) plen 4
>>      LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
>>        Status: Success (0x00)
>>
>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>> ---
>> include/net/bluetooth/hci.h |  7 +++++++
>> net/bluetooth/hci_event.c   |  2 ++
>> net/bluetooth/hci_request.c | 22 ++++++++++++++++++++--
>> net/bluetooth/hci_request.h |  1 +
>> net/bluetooth/mgmt.c        |  3 +++
>> 5 files changed, 33 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index 5b84d9a..1a68530 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -1648,6 +1648,13 @@ struct hci_cp_le_set_ext_scan_rsp_data {
>>
>> #define LE_SET_ADV_DATA_NO_FRAG               0x01
>>
>> +#define HCI_OP_LE_REMOVE_ADV_SET     0x203c
>> +struct hci_cp_le_remove_adv_set {
>> +     __u8  handle;
>> +} __packed;
>> +
>> +#define HCI_OP_LE_CLEAR_ADV_SETS     0x203d
>> +
>> /* ---- HCI Events ---- */
>> #define HCI_EV_INQUIRY_COMPLETE               0x01
>>
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index e17002f..e703880 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -1129,6 +1129,8 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
>>                       queue_delayed_work(hdev->workqueue,
>>                                          &conn->le_conn_timeout,
>>                                          conn->conn_timeout);
>> +     } else {
>> +             hci_dev_clear_flag(hdev, HCI_LE_ADV);
>>       }
>>
>>       hci_dev_unlock(hdev);
>> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
>> index 5fde161..7051c5b 100644
>> --- a/net/bluetooth/hci_request.c
>> +++ b/net/bluetooth/hci_request.c
>> @@ -933,9 +933,19 @@ static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
>>
>> void __hci_req_disable_advertising(struct hci_request *req)
>> {
>> -     u8 enable = 0x00;
>> +     if (ext_adv_capable(req->hdev)) {
>> +             struct hci_cp_le_set_ext_adv_enable cp;
>>
>> -     hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
>> +             cp.enable = 0x00;
>> +             /* Disable all adv sets */
>> +             cp.num_of_sets = 0x00;
>
> I would prefer a more details comment that we can disable all sets since we only support one set at the moment anyway.
>
>> +
>> +             hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(cp), &cp);
>> +     } else {
>> +             u8 enable = 0x00;
>> +
>> +             hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
>> +     }
>> }
>>
>> static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
>> @@ -1417,6 +1427,11 @@ static void adv_timeout_expire(struct work_struct *work)
>>       hci_dev_unlock(hdev);
>> }
>>
>> +void __hci_req_clear_ext_adv_sets(struct hci_request *req)
>> +{
>> +     hci_req_add(req, HCI_OP_LE_REMOVE_ADV_SET, 0, NULL);
>
> Actually this needs a comment as well to note that this is fine since we are just using a single set at the moment.

Clear ext adv set can be used only to clear all the adv sets. So this
will be same
in case of single set or more than one set.

Thanks,
Jaganath

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

* Re: [PATCH v4 12/13] Bluetooth: Implement Set ADV set random address
  2018-07-14 20:52   ` Marcel Holtmann
@ 2018-07-16  9:57     ` Jaganath K
  0 siblings, 0 replies; 39+ messages in thread
From: Jaganath K @ 2018-07-16  9:57 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,

On Sun, Jul 15, 2018 at 2:22 AM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
> Hi Jaganath,
>
>> This basically sets the random address for the instance 0.
>> Random address can be set only if the instance is created which
>> is done in Set ext adv param.
>>
>> This introduces a hci_get_random_address() which returns the
>> own address type and random address (rpa, nrpa or static) based
>> on the instance flags and hdev flags. New function is required
>> since own address type should be known before setting adv params
>> but address can be set only after setting params.
>>
>> < HCI Command: LE Set Advertising Set Random Address (0x08|0x0035) plen =
7
>>        Advertising handle: 0x00
>>        Advertising random address: 3C:8E:56:9B:77:84 (OUI 3C-8E-56)
>>> HCI Event: Command Complete (0x0e) plen 4
>>      LE Set Advertising Set Random Address (0x08|0x0035) ncmd 1
>>        Status: Success (0x00)
>>
>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>> ---
>> include/net/bluetooth/hci.h |   6 +++
>> net/bluetooth/hci_conn.c    |  23 +++++++++
>> net/bluetooth/hci_event.c   |  24 ++++++++++
>> net/bluetooth/hci_request.c | 111 ++++++++++++++++++++++++++++++++++++++=
+++++-
>> net/bluetooth/hci_request.h |   3 ++
>> 5 files changed, 166 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index 1a68530..40a532a 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -1655,6 +1655,12 @@ struct hci_cp_le_remove_adv_set {
>>
>> #define HCI_OP_LE_CLEAR_ADV_SETS      0x203d
>>
>> +#define HCI_OP_LE_SET_ADV_SET_RAND_ADDR      0x2035
>> +struct hci_cp_le_set_adv_set_rand_addr {
>> +     __u8  handle;
>> +     bdaddr_t  bdaddr;
>> +} __packed;
>> +
>> /* ---- HCI Events ---- */
>> #define HCI_EV_INQUIRY_COMPLETE               0x01
>>
>> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
>> index fc27bd8..cf180b24 100644
>> --- a/net/bluetooth/hci_conn.c
>> +++ b/net/bluetooth/hci_conn.c
>> @@ -875,6 +875,14 @@ static void hci_req_directed_advertising(struct hci=
_request *req,
>>
>>       if (ext_adv_capable(hdev)) {
>>               struct hci_cp_le_set_ext_adv_params cp;
>> +             bdaddr_t random_addr;
>> +
>> +             /* Set require_privacy to false so that the remote device =
has a
>> +              * chance of identifying us.
>> +              */
>> +             if (hci_get_random_address(hdev, false, conn_use_rpa(conn)=
,
>> +                                        &own_addr_type, &random_addr) <=
 0)
>> +                     return;
>>
>>               memset(&cp, 0, sizeof(cp));
>>
>> @@ -891,6 +899,21 @@ static void hci_req_directed_advertising(struct hci=
_request *req,
>>
>>               hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp),=
 &cp);
>>
>> +             if (own_addr_type =3D=3D ADDR_LE_DEV_RANDOM &&
>> +                 bacmp(&random_addr, BDADDR_ANY) &&
>> +                 bacmp(&random_addr, &hdev->random_addr)) {
>> +                     struct hci_cp_le_set_adv_set_rand_addr cp;
>> +
>> +                     memset(&cp, 0, sizeof(cp));
>> +
>> +                     cp.handle =3D 0;
>> +                     bacpy(&cp.bdaddr, &random_addr);
>> +
>> +                     hci_req_add(req,
>> +                                 HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
>> +                                 sizeof(cp), &cp);
>> +             }
>> +
>>               __hci_req_enable_ext_advertising(req);
>>       } else {
>>               struct hci_cp_le_set_adv_param cp;
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index e703880..dfb2a82 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -1061,6 +1061,26 @@ static void hci_cc_le_set_default_phy(struct hci_=
dev *hdev, struct sk_buff *skb)
>>       hdev->le_tx_def_phys =3D cp->tx_phys;
>>       hdev->le_rx_def_phys =3D cp->rx_phys;
>>
>> +        hci_dev_unlock(hdev);
>
> We have some whitespace damage here.
>
>> +}
>> +
>> +static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
>> +                                              struct sk_buff *skb)
>> +{
>> +        __u8 status =3D *((__u8 *) skb->data);
>> +        struct hci_cp_le_set_adv_set_rand_addr *cp;
>> +
>> +     if (status)
>> +             return;
>> +
>> +     cp =3D hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
>> +     if (!cp)
>> +             return;
>> +
>> +     hci_dev_lock(hdev);
>> +
>> +     bacpy(&hdev->random_addr, &cp->bdaddr);
>
> Same as with hdev->adv_tx_power, you can not do that. You need to store t=
hese per adv instance. I really like to keep the parts that we used for leg=
acy commands different than others.
>

Ok.

>> +
>>       hci_dev_unlock(hdev);
>> }
>>
>> @@ -3272,6 +3292,10 @@ static void hci_cmd_complete_evt(struct hci_dev *=
hdev, struct sk_buff *skb,
>>               hci_cc_le_set_ext_adv_enable(hdev, skb);
>>               break;
>>
>> +     case HCI_OP_LE_SET_ADV_SET_RAND_ADDR:
>> +             hci_cc_le_set_adv_set_random_addr(hdev, skb);
>> +             break;
>> +
>>       default:
>>               BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
>>               break;
>> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
>> index 7051c5b..6825a65 100644
>> --- a/net/bluetooth/hci_request.c
>> +++ b/net/bluetooth/hci_request.c
>> @@ -1427,6 +1427,87 @@ static void adv_timeout_expire(struct work_struct=
 *work)
>>       hci_dev_unlock(hdev);
>> }
>>
>> +int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
>> +                        bool use_rpa, u8 *own_addr_type, bdaddr_t *rand=
_addr)
>> +{
>> +     int err;
>> +
>> +     bacpy(rand_addr, BDADDR_ANY);
>> +
>> +     /* If privacy is enabled use a resolvable private address. If
>> +      * current RPA has expired then generate a new one.
>> +      */
>> +     if (use_rpa) {
>> +             *own_addr_type =3D ADDR_LE_DEV_RANDOM;
>> +
>> +             if (!hci_dev_test_and_clear_flag(hdev, HCI_RPA_EXPIRED) &&
>> +                 !bacmp(&hdev->random_addr, &hdev->rpa))
>> +                     return 0;
>> +
>> +             err =3D smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
>> +             if (err < 0) {
>> +                     BT_ERR("%s failed to generate new RPA", hdev->name=
);
>> +                     return err;
>> +             }
>> +
>> +             bacpy(rand_addr, &hdev->rpa);
>> +
>> +             return 0;
>> +     }
>> +
>> +     /* In case of required privacy without resolvable private address,
>> +      * use an non-resolvable private address. This is useful for activ=
e
>> +      * scanning and non-connectable advertising.
>> +      */
>> +     if (require_privacy) {
>> +             bdaddr_t nrpa;
>> +
>> +             while (true) {
>> +                     /* The non-resolvable private address is generated
>> +                      * from random six bytes with the two most signifi=
cant
>> +                      * bits cleared.
>> +                      */
>> +                     get_random_bytes(&nrpa, 6);
>> +                     nrpa.b[5] &=3D 0x3f;
>> +
>> +                     /* The non-resolvable private address shall not be
>> +                      * equal to the public address.
>> +                      */
>> +                     if (bacmp(&hdev->bdaddr, &nrpa))
>> +                             break;
>> +             }
>> +
>> +             *own_addr_type =3D ADDR_LE_DEV_RANDOM;
>> +             bacpy(rand_addr, &nrpa);
>> +
>> +             return 0;
>> +     }
>> +
>> +     /* If forcing static address is in use or there is no public
>> +      * address use the static address as random address
>> +      *
>> +      * In case BR/EDR has been disabled on a dual-mode controller
>> +      * and a static address has been configured, then use that
>> +      * address instead of the public BR/EDR address.
>> +      */
>> +     if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
>> +         !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
>> +         (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
>> +          bacmp(&hdev->static_addr, BDADDR_ANY))) {
>> +             *own_addr_type =3D ADDR_LE_DEV_RANDOM;
>> +             bacpy(rand_addr, &hdev->static_addr);
>> +
>> +             return 0;
>> +     }
>> +
>> +     /* Neither privacy nor static address is being used so use a
>> +      * public address.
>> +      */
>> +     *own_addr_type =3D ADDR_LE_DEV_PUBLIC;
>> +
>> +     return 0;
>> +}
>> +
>
> So I am not convinced that we need all of this. For example we only use t=
his for advertising. So our decision for active scanning is useless.
>

Ok. I will remove it as well as force static address part as i think
its not relevant for adv.

> What I think is best that we actually add rand_addr to the adv instance s=
tructure and just calculate what random address we want to use ahead of tim=
e and keep it stored in the instance. I mean, we want to rotate the address=
 for each instance independently.
>

So I think we would need separate rpa timer and expire flag also for
each instance.

Thanks,
Jaganath

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

* Re: [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command
  2018-07-15  7:56     ` Jaganath K
@ 2018-07-16 13:08       ` Marcel Holtmann
  2018-07-16 13:46         ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-16 13:08 UTC (permalink / raw)
  To: Jaganath K; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Jaganath,

>>> This commands basically retrieve the supported packet types of
>>> BREDR and supported PHYs of the controller.
>>> 
>>> BR_1M_1SLOT, LE_1M_TX and LE_1M_RX would be supported by default.
>>> Other PHYs are supported based on the local features.
>>> 
>>> @ MGMT Command: Get PHY Configuration (0x0044) plen 0
>>> @ MGMT Event: Command Complete (0x0001) plen 15
>>>     Get PHY Configuration (0x0044) plen 12
>>>       Status: Success (0x00)
>>>       Supported PHYs: 0x7fff
>>>         BR 1M 1SLOT
>>>         BR 1M 3SLOT
>>>         BR 1M 5SLOT
>>>         EDR 2M 1SLOT
>>>         EDR 2M 3SLOT
>>>         EDR 2M 5SLOT
>>>         EDR 3M 1SLOT
>>>         EDR 3M 3SLOT
>>>         EDR 3M 5SLOT
>>>         LE 1M TX
>>>         LE 1M RX
>>>         LE 2M TX
>>>         LE 2M RX
>>>         LE CODED TX
>>>         LE CODED RX
>>>       Configurable PHYs: 0x79fe
>>>         BR 1M 3SLOT
>>>         BR 1M 5SLOT
>>>         EDR 2M 1SLOT
>>>         EDR 2M 3SLOT
>>>         EDR 2M 5SLOT
>>>         EDR 3M 1SLOT
>>>         EDR 3M 3SLOT
>>>         EDR 3M 5SLOT
>>>         LE 2M TX
>>>         LE 2M RX
>>>         LE CODED TX
>>>         LE CODED RX
>>>       Selected PHYs: 0x07ff
>>>         BR 1M 1SLOT
>>>         BR 1M 3SLOT
>>>         BR 1M 5SLOT
>>>         EDR 2M 1SLOT
>>>         EDR 2M 3SLOT
>>>         EDR 2M 5SLOT
>>>         EDR 3M 1SLOT
>>>         EDR 3M 3SLOT
>>>         EDR 3M 5SLOT
>>>         LE 1M TX
>>>         LE 1M RX
>>> 
>>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>>> ---
>>> include/net/bluetooth/hci.h      |  14 ++++
>>> include/net/bluetooth/hci_core.h |   4 ++
>>> include/net/bluetooth/mgmt.h     |  24 +++++++
>>> net/bluetooth/mgmt.c             | 149 +++++++++++++++++++++++++++++++++++++++
>>> 4 files changed, 191 insertions(+)
>>> 
>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>> index 664fe1e..89bf800 100644
>>> --- a/include/net/bluetooth/hci.h
>>> +++ b/include/net/bluetooth/hci.h
>>> @@ -291,6 +291,14 @@ enum {
>>> #define HCI_DH3               0x0800
>>> #define HCI_DH5               0x8000
>>> 
>>> +/* HCI packet types inverted masks */
>>> +#define HCI_2DH1     0x0002
>>> +#define HCI_3DH1     0x0004
>>> +#define HCI_2DH3     0x0100
>>> +#define HCI_3DH3     0x0200
>>> +#define HCI_2DH5     0x1000
>>> +#define HCI_3DH5     0x2000
>>> +
>>> #define HCI_HV1               0x0020
>>> #define HCI_HV2               0x0040
>>> #define HCI_HV3               0x0080
>>> @@ -354,6 +362,8 @@ enum {
>>> #define LMP_PCONTROL  0x04
>>> #define LMP_TRANSPARENT       0x08
>>> 
>>> +#define LMP_EDR_2M           0x02
>>> +#define LMP_EDR_3M           0x04
>>> #define LMP_RSSI_INQ  0x40
>>> #define LMP_ESCO      0x80
>>> 
>>> @@ -361,7 +371,9 @@ enum {
>>> #define LMP_EV5               0x02
>>> #define LMP_NO_BREDR  0x20
>>> #define LMP_LE                0x40
>>> +#define LMP_EDR_3SLOT        0x80
>>> 
>>> +#define LMP_EDR_5SLOT        0x01
>>> #define LMP_SNIFF_SUBR        0x02
>>> #define LMP_PAUSE_ENC 0x04
>>> #define LMP_EDR_ESCO_2M       0x20
>>> @@ -399,6 +411,8 @@ enum {
>>> #define HCI_LE_PING                   0x10
>>> #define HCI_LE_DATA_LEN_EXT           0x20
>>> #define HCI_LE_EXT_SCAN_POLICY                0x80
>>> +#define HCI_LE_PHY_2M                        0x01
>>> +#define HCI_LE_PHY_CODED             0x08
>>> #define HCI_LE_CHAN_SEL_ALG2          0x40
>> 
>> I see why you used _SET in the previous patch. Maybe it is ok to leave it that way.
>> 
>>> 
>>> /* Connection modes */
>>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>>> index 71f79df..a64d13f 100644
>>> --- a/include/net/bluetooth/hci_core.h
>>> +++ b/include/net/bluetooth/hci_core.h
>>> @@ -1141,6 +1141,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
>>> #define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
>>> #define lmp_ext_feat_capable(dev)  ((dev)->features[0][7] & LMP_EXTFEATURES)
>>> #define lmp_transp_capable(dev)    ((dev)->features[0][2] & LMP_TRANSPARENT)
>>> +#define lmp_edr_2m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_2M)
>>> +#define lmp_edr_3m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_3M)
>>> +#define lmp_edr_3slot_capable(dev) ((dev)->features[0][4] & LMP_EDR_3SLOT)
>>> +#define lmp_edr_5slot_capable(dev) ((dev)->features[0][5] & LMP_EDR_5SLOT)
>> 
>> Lets split the non-mgmt related changes from the mgmt ones into separate patches.
>> 
>>> 
>>> /* ----- Extended LMP capabilities ----- */
>>> #define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_MASTER)
>>> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
>>> index e7303ee..16dddb1 100644
>>> --- a/include/net/bluetooth/mgmt.h
>>> +++ b/include/net/bluetooth/mgmt.h
>>> @@ -604,6 +604,30 @@ struct mgmt_cp_set_appearance {
>>> } __packed;
>>> #define MGMT_SET_APPEARANCE_SIZE      2
>>> 
>>> +#define MGMT_OP_GET_PHY_CONFIGURATION        0x0044
>>> +#define MGMT_GET_PHY_CONFIGURATION_SIZE              0
>>> +struct mgmt_rp_get_phy_confguration {
>>> +     __le32  supported_phys;
>>> +     __le32  configurable_phys;
>>> +     __le32  selected_phys;
>>> +} __packed;
>>> +
>>> +#define MGMT_PHY_BR_1M_1SLOT 0x00000001
>>> +#define MGMT_PHY_BR_1M_3SLOT 0x00000002
>>> +#define MGMT_PHY_BR_1M_5SLOT 0x00000004
>>> +#define MGMT_PHY_EDR_2M_1SLOT        0x00000008
>>> +#define MGMT_PHY_EDR_2M_3SLOT        0x00000010
>>> +#define MGMT_PHY_EDR_2M_5SLOT        0x00000020
>>> +#define MGMT_PHY_EDR_3M_1SLOT        0x00000040
>>> +#define MGMT_PHY_EDR_3M_3SLOT        0x00000080
>>> +#define MGMT_PHY_EDR_3M_5SLOT        0x00000100
>>> +#define MGMT_PHY_LE_1M_TX            0x00000200
>>> +#define MGMT_PHY_LE_1M_RX            0x00000400
>>> +#define MGMT_PHY_LE_2M_TX            0x00000800
>>> +#define MGMT_PHY_LE_2M_RX            0x00001000
>>> +#define MGMT_PHY_LE_CODED_TX 0x00002000
>>> +#define MGMT_PHY_LE_CODED_RX 0x00004000
>>> +
>>> #define MGMT_EV_CMD_COMPLETE          0x0001
>>> struct mgmt_ev_cmd_complete {
>>>      __le16  opcode;
>>> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
>>> index 8a80d48..4a31d4d 100644
>>> --- a/net/bluetooth/mgmt.c
>>> +++ b/net/bluetooth/mgmt.c
>>> @@ -617,6 +617,126 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev,
>>>                               &rp, sizeof(rp));
>>> }
>>> 
>>> +static u32 get_supported_phys(struct hci_dev *hdev)
>>> +{
>>> +     u32 supported_phys = 0;
>>> +
>>> +     if (lmp_bredr_capable(hdev)) {
>>> +             supported_phys |= MGMT_PHY_BR_1M_1SLOT;
>>> +
>>> +             if (hdev->features[0][0] & LMP_3SLOT)
>>> +                     supported_phys |= MGMT_PHY_BR_1M_3SLOT;
>>> +
>>> +             if (hdev->features[0][0] & LMP_5SLOT)
>>> +                     supported_phys |= MGMT_PHY_BR_1M_5SLOT;
>>> +
>>> +             if (lmp_edr_2m_capable(hdev)) {
>>> +                     supported_phys |= MGMT_PHY_EDR_2M_1SLOT;
>>> +
>>> +                     if (lmp_edr_3slot_capable(hdev))
>>> +                             supported_phys |= MGMT_PHY_EDR_2M_3SLOT;
>>> +
>>> +                     if (lmp_edr_5slot_capable(hdev))
>>> +                             supported_phys |= MGMT_PHY_EDR_2M_5SLOT;
>>> +
>>> +                     if (lmp_edr_3m_capable(hdev)) {
>>> +                             supported_phys |= MGMT_PHY_EDR_3M_1SLOT;
>>> +
>>> +                             if (lmp_edr_3slot_capable(hdev))
>>> +                                     supported_phys |= MGMT_PHY_EDR_3M_3SLOT;
>>> +
>>> +                             if (lmp_edr_5slot_capable(hdev))
>>> +                                     supported_phys |= MGMT_PHY_EDR_3M_5SLOT;
>>> +                     }
>>> +             }
>>> +     }
>>> +
>>> +     if (lmp_le_capable(hdev)) {
>>> +             supported_phys |= MGMT_PHY_LE_1M_TX;
>>> +             supported_phys |= MGMT_PHY_LE_1M_RX;
>>> +
>>> +             if (hdev->le_features[1] & HCI_LE_PHY_2M) {
>>> +                     supported_phys |= MGMT_PHY_LE_2M_TX;
>>> +                     supported_phys |= MGMT_PHY_LE_2M_RX;
>>> +             }
>> 
>> Extra empty line here.
>> 
>>> +             if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
>>> +                     supported_phys |= MGMT_PHY_LE_CODED_TX;
>>> +                     supported_phys |= MGMT_PHY_LE_CODED_RX;
>>> +             }
>>> +     }
>>> +
>>> +     return supported_phys;
>>> +}
>>> +
>>> +static u32 get_selected_phys(struct hci_dev *hdev)
>>> +{
>>> +     u32 selected_phys = 0;
>>> +
>>> +     if (lmp_bredr_capable(hdev)) {
>>> +             selected_phys |= MGMT_PHY_BR_1M_1SLOT;
>>> +
>>> +             if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
>>> +                     selected_phys |= MGMT_PHY_BR_1M_3SLOT;
>>> +
>>> +             if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
>>> +                     selected_phys |= MGMT_PHY_BR_1M_5SLOT;
>>> +
>>> +             if (lmp_edr_2m_capable(hdev)) {
>>> +                     if (!(hdev->pkt_type & HCI_2DH1))
>>> +                             selected_phys |= MGMT_PHY_EDR_2M_1SLOT;
>>> +
>>> +                     if (lmp_edr_3slot_capable(hdev) &&
>>> +                             !(hdev->pkt_type & HCI_2DH3))
>> 
>> these need to align according to the netdev coding style.
>> 
>>> +                             selected_phys |= MGMT_PHY_EDR_2M_3SLOT;
>>> +
>>> +                     if (lmp_edr_5slot_capable(hdev) &&
>>> +                             !(hdev->pkt_type & HCI_2DH5))
>>> +                             selected_phys |= MGMT_PHY_EDR_2M_5SLOT;
>>> +
>>> +                     if (lmp_edr_3m_capable(hdev)) {
>>> +                             if (!(hdev->pkt_type & HCI_3DH1))
>>> +                                     selected_phys |= MGMT_PHY_EDR_3M_1SLOT;
>>> +
>>> +                             if (lmp_edr_3slot_capable(hdev) &&
>>> +                                     !(hdev->pkt_type & HCI_3DH3))
>>> +                                     selected_phys |= MGMT_PHY_EDR_3M_3SLOT;
>>> +
>>> +                             if (lmp_edr_5slot_capable(hdev) &&
>>> +                                     !(hdev->pkt_type & HCI_3DH5))
>>> +                                     selected_phys |= MGMT_PHY_EDR_3M_5SLOT;
>>> +                     }
>>> +             }
>>> +     }
>>> +
>>> +     if (lmp_le_capable(hdev)) {
>>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
>>> +                     selected_phys |= MGMT_PHY_LE_1M_TX;
>>> +
>>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
>>> +                     selected_phys |= MGMT_PHY_LE_1M_RX;
>>> +
>>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
>>> +                     selected_phys |= MGMT_PHY_LE_2M_TX;
>>> +
>>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
>>> +                     selected_phys |= MGMT_PHY_LE_2M_RX;
>>> +
>>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
>>> +                     selected_phys |= MGMT_PHY_LE_CODED_TX;
>>> +
>>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
>>> +                     selected_phys |= MGMT_PHY_LE_CODED_RX;
>>> +     }
>>> +
>>> +     return selected_phys;
>>> +}
>>> +
>>> +static u32 get_configurable_phys(struct hci_dev *hdev)
>>> +{
>>> +     return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
>>> +                     ~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
>> 
>> Here the alignment needs to be also corrected.
>> 
>>> +}
>>> +
>>> static u32 get_supported_settings(struct hci_dev *hdev)
>>> {
>>>      u32 settings = 0;
>>> @@ -654,6 +774,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
>>>          hdev->set_bdaddr)
>>>              settings |= MGMT_SETTING_CONFIGURATION;
>>> 
>>> +     if (get_supported_phys(hdev) & ~(MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_LE_1M_TX |
>>> +                                     MGMT_PHY_LE_1M_RX))
>> 
>> Same here.
>> 
>>> +             settings |= MGMT_SETTING_PHY_CONFIGURATION;
>>> +
>> 
>> Frankly I think that PHY configuration can be unconditionally be listed as supported here. Even on a 4.0 or just a 1.2 device we should hint that PHY configuration is possible.
> 
> If a controller supports only BR 1M 1 SLOT and / or only LE 1M then
> PHY configuration should not be
> set (which is what the check is doing).

we could argue for that, but then I wonder if we are making of life more complicated than it needs to be. I currently see no value in this. I might have suggested something like that in the past, but I feel to see what value we have with that.

If the PHY configuration setting is not present, then it is BR/EDR wild guessing and LE 1M depending on the other settings bits. If PHY configuration set, then you use Get PHY configuration and know exactly. You will never try to interpret that setting bit anymore. You actually get the exact details. So I would always just set it.

I am open for reasons here, but I am failing to see the benefit of anything complex at the moment.

> 
>> 
>>>      return settings;
>>> }
>>> 
>>> @@ -722,6 +846,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
>>>                      settings |= MGMT_SETTING_STATIC_ADDRESS;
>>>      }
>>> 
>>> +     if (phys_configured(hdev))
>>> +             settings |= MGMT_SETTING_PHY_CONFIGURATION;
>>> +
>> 
>> What is this conditional doing? You need to add a comment here explaining when we set configuration flag in current settings and when not.
> 
> This checks whether any PHY is deselected in BREDR or selected in LE.
> Will add comment.
> 
> So basically it will be set in supported settings if any PHYs other
> than the basic PHYs is supported
> and will set in current settings if any PHYs are configured
> (deselected in BREDR or selected in LE).

So for MGMT_SETTING_CONFIGURATION, we also never expose it in the current settings, so until I figure out a need for this, we should not bother with complex code for this either.

We can really figure out later on how we use the current settings info of the PHY configuration. Frankly, I have no idea what a default PHY config actually looks like with the combination of BR, BR/EDR, single vs dual and LE only controllers.

Regards

Marcel


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

* Re: [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types
  2018-07-15  9:52     ` Jaganath K
@ 2018-07-16 13:09       ` Marcel Holtmann
  0 siblings, 0 replies; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-16 13:09 UTC (permalink / raw)
  To: Jaganath K; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Jaganath,

>>> This patch defines the extended ADV types and handle it in ADV report.
>>> 
>>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>>> ---
>>> include/net/bluetooth/hci.h |  8 ++++++++
>>> net/bluetooth/hci_event.c   | 49 +++++++++++++++++++++++++++++++--------------
>>> 2 files changed, 42 insertions(+), 15 deletions(-)
>>> 
>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>> index 3584632..fcd1d57 100644
>>> --- a/include/net/bluetooth/hci.h
>>> +++ b/include/net/bluetooth/hci.h
>>> @@ -1977,6 +1977,14 @@ struct hci_ev_le_conn_complete {
>>> #define LE_LEGACY_SCAN_RSP_ADV                0x001b
>>> #define LE_LEGACY_SCAN_RSP_ADV_SCAN   0x001a
>>> 
>>> +/* Extended Advertising event types */
>>> +#define LE_EXT_ADV_NON_CONN_IND              0x0000
>>> +#define LE_EXT_ADV_CONN_IND          0x0001
>>> +#define LE_EXT_ADV_SCAN_IND          0x0002
>>> +#define LE_EXT_ADV_DIRECT_IND                0x0004
>>> +#define LE_EXT_ADV_SCAN_RSP          0x0008
>>> +#define LE_EXT_ADV_LEGACY_PDU                0x0010
>>> +
>>> #define ADDR_LE_DEV_PUBLIC    0x00
>>> #define ADDR_LE_DEV_RANDOM    0x01
>>> 
>>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>>> index 6942315..027abe6 100644
>>> --- a/net/bluetooth/hci_event.c
>>> +++ b/net/bluetooth/hci_event.c
>>> @@ -5137,20 +5137,39 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
>>>      hci_dev_unlock(hdev);
>>> }
>>> 
>>> -static u8 convert_legacy_evt_type(u16 evt_type)
>>> -{
>>> -     switch (evt_type) {
>>> -     case LE_LEGACY_ADV_IND:
>>> -             return LE_ADV_IND;
>>> -     case LE_LEGACY_ADV_DIRECT_IND:
>>> -             return LE_ADV_DIRECT_IND;
>>> -     case LE_LEGACY_ADV_SCAN_IND:
>>> -             return LE_ADV_SCAN_IND;
>>> -     case LE_LEGACY_NONCONN_IND:
>>> -             return LE_ADV_NONCONN_IND;
>>> -     case LE_LEGACY_SCAN_RSP_ADV:
>>> -     case LE_LEGACY_SCAN_RSP_ADV_SCAN:
>>> -             return LE_ADV_SCAN_RSP;
>>> +static u8 convert_ext_evt_type(u16 evt_type)
>>> +{
>>> +     if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
>>> +             switch (evt_type) {
>>> +             case LE_LEGACY_ADV_IND:
>>> +                     return LE_ADV_IND;
>>> +             case LE_LEGACY_ADV_DIRECT_IND:
>>> +                     return LE_ADV_DIRECT_IND;
>>> +             case LE_LEGACY_ADV_SCAN_IND:
>>> +                     return LE_ADV_SCAN_IND;
>>> +             case LE_LEGACY_NONCONN_IND:
>>> +                     return LE_ADV_NONCONN_IND;
>>> +             case LE_LEGACY_SCAN_RSP_ADV:
>>> +             case LE_LEGACY_SCAN_RSP_ADV_SCAN:
>>> +                     return LE_ADV_SCAN_RSP;
>>> +             }
>> 
>> I would do a return here since only the legacy part is special.
>> 
>>> +     } else {
>>> +             if (evt_type & LE_EXT_ADV_CONN_IND) {
>>> +                     if (evt_type & LE_EXT_ADV_DIRECT_IND)
>>> +                             return LE_ADV_DIRECT_IND;
>>> +
>>> +                     return LE_ADV_IND;
>>> +             }
>>> +
>>> +             if (evt_type & LE_EXT_ADV_SCAN_RSP)
>>> +                     return LE_ADV_SCAN_RSP;
>>> +
>>> +             if (evt_type & LE_EXT_ADV_SCAN_IND)
>>> +                     return LE_ADV_SCAN_IND;
>>> +
>>> +             if (evt_type == LE_EXT_ADV_NON_CONN_IND ||
>>> +                 evt_type & LE_EXT_ADV_DIRECT_IND)
>>> +                     return LE_ADV_NONCONN_IND;
>> 
>> Why do we have one == match here and the rest are bit checks.
>> 
>>>      }
>>> 
>>>      BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
>>> @@ -5172,7 +5191,7 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
>>>              u16 evt_type;
>>> 
>>>              evt_type = __le16_to_cpu(ev->evt_type);
>>> -             legacy_evt_type = convert_legacy_evt_type(evt_type);
>>> +             legacy_evt_type = convert_ext_evt_type(evt_type);
>> 
>> So ext_evt_type_to_legacy might be a better function name here.
>> 
>>>              if (legacy_evt_type != LE_ADV_INVALID) {
>> 
>> I might have asked this before, when are we reaching _INVALID here?
>> 
> 
> It will be hit in case of an unknown advertising pkt type.

I have no idea on how the controller can give us that until we explicitly enabled / asked for it, but if so, then please add a clear comment here.

Regards

Marcel


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

* Re: [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command
  2018-07-15  9:36     ` Jaganath K
@ 2018-07-16 13:14       ` Marcel Holtmann
  0 siblings, 0 replies; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-16 13:14 UTC (permalink / raw)
  To: Jaganath K; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Jaganath,

>>> This enables user to set phys which will be used in all subsequent
>>> connections. Also host will use the same in LE scanning as well.
>>> 
>>> This patch also implements PHY Changed event which will be
>>> triggered whenever default PHYs change.
>>> 
>>> This also adds PHY_CONFIGURATION to mgmt settings which set
>>> in the supported settings if controller supports 2/3 slot
>>> or 2M/#M in BREDR controller and 2M or CODED in case of LE
>>> and set in current settings if any of them is selected
>>> 
>>> @ MGMT Command: Set PHY Configuration (0x0045) plen 4
>>>       Selected PHYs: 0x7fff
>>>         BR 1M 1SLOT
>>>         BR 1M 3SLOT
>>>         BR 1M 5SLOT
>>>         EDR 2M 1SLOT
>>>         EDR 2M 3SLOT
>>>         EDR 2M 5SLOT
>>>         EDR 3M 1SLOT
>>>         EDR 3M 3SLOT
>>>         EDR 3M 5SLOT
>>>         LE 1M TX
>>>         LE 1M RX
>>>         LE 2M TX
>>>         LE 2M RX
>>>         LE CODED TX
>>>         LE CODED RX
>>> < HCI Command: LE Set Default PHY (0x08|0x0031) plen 3
>>>       All PHYs preference: 0x00
>>>       TX PHYs preference: 0x07
>>>         LE 1M
>>>         LE 2M
>>>         LE Coded
>>>       RX PHYs preference: 0x07
>>>         LE 1M
>>>         LE 2M
>>>         LE Coded
>>>> HCI Event: Command Complete (0x0e) plen 4
>>>     LE Set Default PHY (0x08|0x0031) ncmd 1
>>>       Status: Success (0x00)
>>> @ MGMT Event: Command Complete (0x0001) plen 3
>>>     Set PHY Configuration (0x0045) plen 0
>>>       Status: Success (0x00)
>>> @ MGMT Event: PHY Configuration Changed (0x0026) plen 4
>>>       Selected PHYs: 0x7fff
>>>         BR 1M 1SLOT
>>>         BR 1M 3SLOT
>>>         BR 1M 5SLOT
>>>         EDR 2M 1SLOT
>>>         EDR 2M 3SLOT
>>>         EDR 2M 5SLOT
>>>         EDR 3M 1SLOT
>>>         EDR 3M 3SLOT
>>>         EDR 3M 5SLOT
>>>         LE 1M TX
>>>         LE 1M RX
>>>         LE 2M TX
>>>         LE 2M RX
>>>         LE CODED TX
>>>         LE CODED RX
>>> 
>>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>>> ---
>>> include/net/bluetooth/hci.h      |   1 +
>>> include/net/bluetooth/hci_core.h |   1 +
>>> include/net/bluetooth/mgmt.h     |  25 +++++
>>> net/bluetooth/hci_core.c         |   4 +
>>> net/bluetooth/hci_event.c        |  26 +++++
>>> net/bluetooth/hci_sock.c         |   1 +
>>> net/bluetooth/mgmt.c             | 221 +++++++++++++++++++++++++++++++++++++++
>>> 7 files changed, 279 insertions(+)
>>> 
>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>> index 89bf800..d0f7657 100644
>>> --- a/include/net/bluetooth/hci.h
>>> +++ b/include/net/bluetooth/hci.h
>>> @@ -214,6 +214,7 @@ enum {
>>>      HCI_MGMT_DEV_CLASS_EVENTS,
>>>      HCI_MGMT_LOCAL_NAME_EVENTS,
>>>      HCI_MGMT_OOB_DATA_EVENTS,
>>> +     HCI_MGMT_PHY_CHANGED_EVENTS,
>>> };
>> 
>> is this really needed? These flags are used for events that are conditional. Meaning they are send or not send depending on what mgmt command a given socket has called. Since PHY configuration is new and has now legacy commands it deprecates, I really wonder what this if for. So you need to explain that and if it is needed, split this out into a separate patch that explains it.
>> 
>>> 
>>> /*
>>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>>> index a64d13f..ab5d494 100644
>>> --- a/include/net/bluetooth/hci_core.h
>>> +++ b/include/net/bluetooth/hci_core.h
>>> @@ -1544,6 +1544,7 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
>>>                          u8 instance);
>>> void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
>>>                            u8 instance);
>>> +int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
>>> 
>>> u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
>>>                    u16 to_multiplier);
>>> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
>>> index 16dddb1..047e98d 100644
>>> --- a/include/net/bluetooth/mgmt.h
>>> +++ b/include/net/bluetooth/mgmt.h
>>> @@ -101,6 +101,7 @@ struct mgmt_rp_read_index_list {
>>> #define MGMT_SETTING_PRIVACY          0x00002000
>>> #define MGMT_SETTING_CONFIGURATION    0x00004000
>>> #define MGMT_SETTING_STATIC_ADDRESS   0x00008000
>>> +#define MGMT_SETTING_PHY_CONFIGURATION  0x00010000
>> 
>> You are already using this in patch 02/13 and that makes this patch series non-bisectable.
>> 
>>> 
>>> #define MGMT_OP_READ_INFO             0x0004
>>> #define MGMT_READ_INFO_SIZE           0
>>> @@ -628,6 +629,25 @@ struct mgmt_rp_get_phy_confguration {
>>> #define MGMT_PHY_LE_CODED_TX  0x00002000
>>> #define MGMT_PHY_LE_CODED_RX  0x00004000
>>> 
>>> +#define MGMT_PHY_BREDR_MASK (MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_BR_1M_3SLOT | \
>>> +                             MGMT_PHY_BR_1M_5SLOT | MGMT_PHY_EDR_2M_1SLOT | \
>>> +                             MGMT_PHY_EDR_2M_3SLOT | MGMT_PHY_EDR_2M_5SLOT | \
>>> +                             MGMT_PHY_EDR_3M_1SLOT | MGMT_PHY_EDR_3M_3SLOT | \
>>> +                             MGMT_PHY_EDR_3M_5SLOT)
>>> +#define MGMT_PHY_LE_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX | \
>>> +                             MGMT_PHY_LE_2M_TX | MGMT_PHY_LE_2M_RX | \
>>> +                             MGMT_PHY_LE_CODED_TX | MGMT_PHY_LE_CODED_RX)
>>> +#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
>>> +                          MGMT_PHY_LE_CODED_TX)
>>> +#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \
>>> +                          MGMT_PHY_LE_CODED_RX)
>>> +
>>> +#define MGMT_OP_SET_PHY_CONFIGURATION        0x0045
>>> +#define MGMT_SET_PHY_CONFIGURATION_SIZE              4
>>> +struct mgmt_cp_set_phy_confguration {
>>> +     __le32  selected_phys;
>>> +} __packed;
>> 
>> The _SIZE constant is normally below the data structure. Please follow the existing style.
>> 
>>> +
>>> #define MGMT_EV_CMD_COMPLETE          0x0001
>>> struct mgmt_ev_cmd_complete {
>>>      __le16  opcode;
>>> @@ -848,3 +868,8 @@ struct mgmt_ev_ext_info_changed {
>>>      __le16  eir_len;
>>>      __u8    eir[0];
>>> } __packed;
>>> +
>>> +#define MGMT_EV_PHY_CONFIGURATION_CHANGED    0x0026
>>> +struct mgmt_ev_phy_configuration_changed {
>>> +     __le32  selected_phys;
>>> +} __packed;
>>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>>> index 432f89f..0d88dc9 100644
>>> --- a/net/bluetooth/hci_core.c
>>> +++ b/net/bluetooth/hci_core.c
>>> @@ -1924,7 +1924,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
>>>              break;
>>> 
>>>      case HCISETPTYPE:
>>> +             if (hdev->pkt_type == ((__u16) dr.dev_opt))
>>> +                     break;
>>> +
>> 
>> What is the extra () doing here? I doubt that is needed.
>> 
>>>              hdev->pkt_type = (__u16) dr.dev_opt;
>>> +             mgmt_phy_configuration_changed(hdev, NULL);
>>>              break;
>> 
>> Also I would do that as a separate patch with a clear commit message that this is for legacy behavior. But now I see why you might need that PHY changed event flag.
>> 
>> So lets really do that in a separate patch to clearly point out legacy behavior and the change needed for handling it. This includes the events flag etc. One question I have is if we care if the event is send all the time or not.
>> 
>> So for a client this is not conflicting information or duplicated information coming along. It just means that someone changed the PHY configuration. This can happen via ioctl or mgmt and frankly an observer mgmt client wouldn't be able to tell the difference anyway. So maybe this is just overkill with no purpose.
> 
> So you mean we dont need the new flag?
> 
>> 
>> Also we might better make mgmt_phy_configuration_changed capable of checking if an event is needed or not. Meaning it should check by itself if something changed or not. Don't remember how we did this for other functions. So something to look into.

Lets put this in a separate patch and go first without it.

>> 
>>> 
>>>      case HCISETACLMTU:
>>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>>> index 6819215..6942315 100644
>>> --- a/net/bluetooth/hci_event.c
>>> +++ b/net/bluetooth/hci_event.c
>>> @@ -1042,6 +1042,28 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
>>>      hci_dev_unlock(hdev);
>>> }
>>> 
>>> +static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
>>> +{
>>> +     __u8 status = *((__u8 *) skb->data);
>>> +     struct hci_cp_le_set_default_phy *cp;
>>> +
>>> +     BT_DBG("%s status 0x%2.2x", hdev->name, status);
>>> +
>>> +     if (status)
>>> +             return;
>>> +
>>> +     cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
>>> +     if (!cp)
>>> +             return;
>>> +
>>> +     hci_dev_lock(hdev);
>>> +
>>> +     hdev->le_tx_def_phys = cp->tx_phys;
>>> +     hdev->le_rx_def_phys = cp->rx_phys;
>>> +
>>> +     hci_dev_unlock(hdev);
>>> +}
>>> +
>>> static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
>>> {
>>>      __u8 *sent, status = *((__u8 *) skb->data);
>>> @@ -3163,6 +3185,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
>>>              hci_cc_le_set_ext_scan_enable(hdev, skb);
>>>              break;
>>> 
>>> +     case HCI_OP_LE_SET_DEFAULT_PHY:
>>> +             hci_cc_le_set_default_phy(hdev, skb);
>>> +             break;
>>> +
>>>      default:
>>>              BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
>>>              break;
>>> diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
>>> index 1506e16..476916c 100644
>>> --- a/net/bluetooth/hci_sock.c
>>> +++ b/net/bluetooth/hci_sock.c
>>> @@ -1328,6 +1328,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
>>>                      hci_sock_set_flag(sk, HCI_MGMT_SETTING_EVENTS);
>>>                      hci_sock_set_flag(sk, HCI_MGMT_DEV_CLASS_EVENTS);
>>>                      hci_sock_set_flag(sk, HCI_MGMT_LOCAL_NAME_EVENTS);
>>> +                     hci_sock_set_flag(sk, HCI_MGMT_PHY_CHANGED_EVENTS);
>>>              }
>>>              break;
>>>      }
>>> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
>>> index 4a31d4d..1c2ed42 100644
>>> --- a/net/bluetooth/mgmt.c
>>> +++ b/net/bluetooth/mgmt.c
>>> @@ -737,6 +737,23 @@ static u32 get_configurable_phys(struct hci_dev *hdev)
>>>                      ~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
>>> }
>>> 
>>> +static bool phys_configured(struct hci_dev *hdev)
>>> +{
>>> +     u32 selected_phys = get_selected_phys(hdev);
>>> +     u32 supported_phys = get_supported_phys(hdev);
>>> +
>>> +     /* If any of BREDR supported PHYs are deselected or
>>> +      *  LE PHYs other than 1M are selected
>> 
>> You have extra spaces in the front.
>> 
>>> +      */
>>> +     if (((supported_phys & MGMT_PHY_BREDR_MASK) !=
>>> +              (selected_phys & MGMT_PHY_BREDR_MASK)) ||
>>> +             ((selected_phys & MGMT_PHY_LE_MASK) &
>>> +               ~(MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX)))
>> 
>> This alignment is not okay. Go over the character per line limit here if needed.
>> 
>> One question though, why are making an exception for LE_1M here?
>> 
> 
> LE is supported will mean that LE_!M is supported and also cannot be
> configured (deselected).

Can you please add comments in front of these complex statements.

> 
>>> +             return true;
>>> +
>>> +     return false;
>>> +}
>>> +
>>> static u32 get_supported_settings(struct hci_dev *hdev)
>>> {
>>>      u32 settings = 0;
>>> @@ -3332,6 +3349,209 @@ static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
>>>                               &rp, sizeof(rp));
>>> }
>>> 
>>> +int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
>>> +{
>>> +     struct mgmt_ev_phy_configuration_changed ev;
>>> +
>>> +     memset(&ev, 0, sizeof(ev));
>>> +
>>> +     ev.selected_phys = cpu_to_le32(get_selected_phys(hdev));
>>> +
>>> +     return mgmt_limited_event(MGMT_EV_PHY_CONFIGURATION_CHANGED, hdev, &ev,
>>> +                               sizeof(ev), HCI_MGMT_PHY_CHANGED_EVENTS,
>>> +                               skip);
>>> +}
>>> +
>>> +static void set_default_phy_complete(struct hci_dev *hdev, u8 status,
>>> +                                  u16 opcode, struct sk_buff *skb)
>>> +{
>>> +     struct mgmt_cp_set_phy_confguration *cp;
>>> +     struct mgmt_pending_cmd *cmd;
>>> +
>>> +     BT_DBG("status 0x%02x", status);
>>> +
>>> +     hci_dev_lock(hdev);
>>> +
>>> +     cmd = pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev);
>>> +     if (!cmd)
>>> +             goto unlock;
>>> +
>>> +     cp = cmd->param;
>>> +
>>> +     if (status) {
>>> +             mgmt_cmd_status(cmd->sk, hdev->id,
>>> +                             MGMT_OP_SET_PHY_CONFIGURATION,
>>> +                             mgmt_status(status));
>>> +     } else {
>>> +             mgmt_cmd_complete(cmd->sk, hdev->id,
>>> +                               MGMT_OP_SET_PHY_CONFIGURATION, 0,
>>> +                               NULL, 0);
>>> +
>>> +             mgmt_phy_configuration_changed(hdev, cmd->sk);
>>> +             new_settings(hdev, cmd->sk);
>> 
>> This new_settings we really need to discuss and document its behavior.
> 
> As per our initial discussion, NewSettings will have PHY Configuration bit set
> if any PHYs other than 1M is selected. I have extended it to BREDR wherein it
> will be set if any of the PHYs are deselected.

And I think we scrap that for now with the new settings events. I fail to see the advantage and we can always do that later.

Regards

Marcel


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

* Re: [PATCH v4 07/13] Bluetooth: Read no of adv sets during init
  2018-07-16  6:27     ` Jaganath K
@ 2018-07-16 13:18       ` Marcel Holtmann
  2018-07-16 13:51         ` Jaganath K
  0 siblings, 1 reply; 39+ messages in thread
From: Marcel Holtmann @ 2018-07-16 13:18 UTC (permalink / raw)
  To: Jaganath K; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Jaganath,

>>> This patch reads the number of advertising sets in the controller
>>> during init and save it in hdev.
>>> 
>>> This also checks ext adv support before send Read Adv TX Power
>>> since legacy and extended Adv commands should not be mixed.
>>> 
>>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>>> ---
>>> include/net/bluetooth/hci.h      |  7 +++++++
>>> include/net/bluetooth/hci_core.h |  4 ++++
>>> net/bluetooth/hci_core.c         | 12 ++++++++++--
>>> net/bluetooth/hci_event.c        | 18 ++++++++++++++++++
>>> 4 files changed, 39 insertions(+), 2 deletions(-)
>>> 
>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>> index fcd1d57..e584863 100644
>>> --- a/include/net/bluetooth/hci.h
>>> +++ b/include/net/bluetooth/hci.h
>>> @@ -411,6 +411,7 @@ enum {
>>> #define HCI_LE_SLAVE_FEATURES         0x08
>>> #define HCI_LE_PING                   0x10
>>> #define HCI_LE_DATA_LEN_EXT           0x20
>>> +#define HCI_LE_EXT_ADV                       0x10
>>> #define HCI_LE_EXT_SCAN_POLICY                0x80
>>> #define HCI_LE_PHY_2M                 0x01
>>> #define HCI_LE_PHY_CODED              0x08
>>> @@ -1580,6 +1581,12 @@ struct hci_cp_le_ext_conn_param {
>>>      __le16 max_ce_len;
>>> } __packed;
>>> 
>>> +#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS        0x203b
>>> +struct hci_rp_le_read_num_supported_adv_sets {
>>> +     __u8  status;
>>> +     __u8  num_of_sets;
>>> +} __packed;
>>> +
>>> /* ---- HCI Events ---- */
>>> #define HCI_EV_INQUIRY_COMPLETE               0x01
>>> 
>>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>>> index 33aab89e..e845ca6 100644
>>> --- a/include/net/bluetooth/hci_core.h
>>> +++ b/include/net/bluetooth/hci_core.h
>>> @@ -222,6 +222,7 @@ struct hci_dev {
>>>      __u8            le_features[8];
>>>      __u8            le_white_list_size;
>>>      __u8            le_resolv_list_size;
>>> +     __u8            le_no_of_adv_sets;
>> 
>> I think our style was to use _num instead of _no. See num_iac for example.
>> 
>>>      __u8            le_states[8];
>>>      __u8            commands[64];
>>>      __u8            hci_ver;
>>> @@ -1180,6 +1181,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
>>> /* Use ext create connection if command is supported */
>>> #define use_ext_conn(dev) ((dev)->commands[37] & 0x80)
>>> 
>>> +/* Extended advertising support */
>>> +#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
>>> +
>>> /* ----- HCI protocols ----- */
>>> #define HCI_PROTO_DEFER             0x01
>>> 
>>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>>> index 0d88dc9..b423587 100644
>>> --- a/net/bluetooth/hci_core.c
>>> +++ b/net/bluetooth/hci_core.c
>>> @@ -715,8 +715,10 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
>>>              hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
>>>                          events);
>>> 
>>> -             if (hdev->commands[25] & 0x40) {
>>> -                     /* Read LE Advertising Channel TX Power */
>>> +             if ((hdev->commands[25] & 0x40) && !ext_adv_capable(hdev)) {
>>> +                     /* Read LE Advertising Channel TX Power only if
>>> +                      * extended advertising is not supported
>>> +                      */
>>>                      hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
>>>              }
>> 
>> Why? I prefer that we read the adv TX power always. Even if we are not using it, it is good to have it in the traces.
> 
> Mixing of legacy and extended commands is forbidden as per HCI TS spec
> Please see  "HCI/GEV/BV-02-C [Disallow Mixing Legacy and Extended Advertising
> Commands]"

and that also includes the Read Adv TX Power command? That is totally strange and I wonder how that affects anything here.

So is it that once you issued Read Adv TX Power you are no longer allowed to use ext adv commands? If that is really the case, then so be it, but this needs a larger comment in front of the if statement to explain what we are doing and why.

Regards

Marcel


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

* Re: [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command
  2018-07-16 13:08       ` Marcel Holtmann
@ 2018-07-16 13:46         ` Jaganath K
  0 siblings, 0 replies; 39+ messages in thread
From: Jaganath K @ 2018-07-16 13:46 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,

On Mon, Jul 16, 2018 at 6:38 PM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
> Hi Jaganath,
>
>>>> This commands basically retrieve the supported packet types of
>>>> BREDR and supported PHYs of the controller.
>>>>
>>>> BR_1M_1SLOT, LE_1M_TX and LE_1M_RX would be supported by default.
>>>> Other PHYs are supported based on the local features.
>>>>
>>>> @ MGMT Command: Get PHY Configuration (0x0044) plen 0
>>>> @ MGMT Event: Command Complete (0x0001) plen 15
>>>>     Get PHY Configuration (0x0044) plen 12
>>>>       Status: Success (0x00)
>>>>       Supported PHYs: 0x7fff
>>>>         BR 1M 1SLOT
>>>>         BR 1M 3SLOT
>>>>         BR 1M 5SLOT
>>>>         EDR 2M 1SLOT
>>>>         EDR 2M 3SLOT
>>>>         EDR 2M 5SLOT
>>>>         EDR 3M 1SLOT
>>>>         EDR 3M 3SLOT
>>>>         EDR 3M 5SLOT
>>>>         LE 1M TX
>>>>         LE 1M RX
>>>>         LE 2M TX
>>>>         LE 2M RX
>>>>         LE CODED TX
>>>>         LE CODED RX
>>>>       Configurable PHYs: 0x79fe
>>>>         BR 1M 3SLOT
>>>>         BR 1M 5SLOT
>>>>         EDR 2M 1SLOT
>>>>         EDR 2M 3SLOT
>>>>         EDR 2M 5SLOT
>>>>         EDR 3M 1SLOT
>>>>         EDR 3M 3SLOT
>>>>         EDR 3M 5SLOT
>>>>         LE 2M TX
>>>>         LE 2M RX
>>>>         LE CODED TX
>>>>         LE CODED RX
>>>>       Selected PHYs: 0x07ff
>>>>         BR 1M 1SLOT
>>>>         BR 1M 3SLOT
>>>>         BR 1M 5SLOT
>>>>         EDR 2M 1SLOT
>>>>         EDR 2M 3SLOT
>>>>         EDR 2M 5SLOT
>>>>         EDR 3M 1SLOT
>>>>         EDR 3M 3SLOT
>>>>         EDR 3M 5SLOT
>>>>         LE 1M TX
>>>>         LE 1M RX
>>>>
>>>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com=
>
>>>> ---
>>>> include/net/bluetooth/hci.h      |  14 ++++
>>>> include/net/bluetooth/hci_core.h |   4 ++
>>>> include/net/bluetooth/mgmt.h     |  24 +++++++
>>>> net/bluetooth/mgmt.c             | 149 +++++++++++++++++++++++++++++++=
++++++++
>>>> 4 files changed, 191 insertions(+)
>>>>
>>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>>> index 664fe1e..89bf800 100644
>>>> --- a/include/net/bluetooth/hci.h
>>>> +++ b/include/net/bluetooth/hci.h
>>>> @@ -291,6 +291,14 @@ enum {
>>>> #define HCI_DH3               0x0800
>>>> #define HCI_DH5               0x8000
>>>>
>>>> +/* HCI packet types inverted masks */
>>>> +#define HCI_2DH1     0x0002
>>>> +#define HCI_3DH1     0x0004
>>>> +#define HCI_2DH3     0x0100
>>>> +#define HCI_3DH3     0x0200
>>>> +#define HCI_2DH5     0x1000
>>>> +#define HCI_3DH5     0x2000
>>>> +
>>>> #define HCI_HV1               0x0020
>>>> #define HCI_HV2               0x0040
>>>> #define HCI_HV3               0x0080
>>>> @@ -354,6 +362,8 @@ enum {
>>>> #define LMP_PCONTROL  0x04
>>>> #define LMP_TRANSPARENT       0x08
>>>>
>>>> +#define LMP_EDR_2M           0x02
>>>> +#define LMP_EDR_3M           0x04
>>>> #define LMP_RSSI_INQ  0x40
>>>> #define LMP_ESCO      0x80
>>>>
>>>> @@ -361,7 +371,9 @@ enum {
>>>> #define LMP_EV5               0x02
>>>> #define LMP_NO_BREDR  0x20
>>>> #define LMP_LE                0x40
>>>> +#define LMP_EDR_3SLOT        0x80
>>>>
>>>> +#define LMP_EDR_5SLOT        0x01
>>>> #define LMP_SNIFF_SUBR        0x02
>>>> #define LMP_PAUSE_ENC 0x04
>>>> #define LMP_EDR_ESCO_2M       0x20
>>>> @@ -399,6 +411,8 @@ enum {
>>>> #define HCI_LE_PING                   0x10
>>>> #define HCI_LE_DATA_LEN_EXT           0x20
>>>> #define HCI_LE_EXT_SCAN_POLICY                0x80
>>>> +#define HCI_LE_PHY_2M                        0x01
>>>> +#define HCI_LE_PHY_CODED             0x08
>>>> #define HCI_LE_CHAN_SEL_ALG2          0x40
>>>
>>> I see why you used _SET in the previous patch. Maybe it is ok to leave =
it that way.
>>>
>>>>
>>>> /* Connection modes */
>>>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/=
hci_core.h
>>>> index 71f79df..a64d13f 100644
>>>> --- a/include/net/bluetooth/hci_core.h
>>>> +++ b/include/net/bluetooth/hci_core.h
>>>> @@ -1141,6 +1141,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
>>>> #define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_T=
X_PWR)
>>>> #define lmp_ext_feat_capable(dev)  ((dev)->features[0][7] & LMP_EXTFEA=
TURES)
>>>> #define lmp_transp_capable(dev)    ((dev)->features[0][2] & LMP_TRANSP=
ARENT)
>>>> +#define lmp_edr_2m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_2=
M)
>>>> +#define lmp_edr_3m_capable(dev)    ((dev)->features[0][3] & LMP_EDR_3=
M)
>>>> +#define lmp_edr_3slot_capable(dev) ((dev)->features[0][4] & LMP_EDR_3=
SLOT)
>>>> +#define lmp_edr_5slot_capable(dev) ((dev)->features[0][5] & LMP_EDR_5=
SLOT)
>>>
>>> Lets split the non-mgmt related changes from the mgmt ones into separat=
e patches.
>>>
>>>>
>>>> /* ----- Extended LMP capabilities ----- */
>>>> #define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_M=
ASTER)
>>>> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt=
.h
>>>> index e7303ee..16dddb1 100644
>>>> --- a/include/net/bluetooth/mgmt.h
>>>> +++ b/include/net/bluetooth/mgmt.h
>>>> @@ -604,6 +604,30 @@ struct mgmt_cp_set_appearance {
>>>> } __packed;
>>>> #define MGMT_SET_APPEARANCE_SIZE      2
>>>>
>>>> +#define MGMT_OP_GET_PHY_CONFIGURATION        0x0044
>>>> +#define MGMT_GET_PHY_CONFIGURATION_SIZE              0
>>>> +struct mgmt_rp_get_phy_confguration {
>>>> +     __le32  supported_phys;
>>>> +     __le32  configurable_phys;
>>>> +     __le32  selected_phys;
>>>> +} __packed;
>>>> +
>>>> +#define MGMT_PHY_BR_1M_1SLOT 0x00000001
>>>> +#define MGMT_PHY_BR_1M_3SLOT 0x00000002
>>>> +#define MGMT_PHY_BR_1M_5SLOT 0x00000004
>>>> +#define MGMT_PHY_EDR_2M_1SLOT        0x00000008
>>>> +#define MGMT_PHY_EDR_2M_3SLOT        0x00000010
>>>> +#define MGMT_PHY_EDR_2M_5SLOT        0x00000020
>>>> +#define MGMT_PHY_EDR_3M_1SLOT        0x00000040
>>>> +#define MGMT_PHY_EDR_3M_3SLOT        0x00000080
>>>> +#define MGMT_PHY_EDR_3M_5SLOT        0x00000100
>>>> +#define MGMT_PHY_LE_1M_TX            0x00000200
>>>> +#define MGMT_PHY_LE_1M_RX            0x00000400
>>>> +#define MGMT_PHY_LE_2M_TX            0x00000800
>>>> +#define MGMT_PHY_LE_2M_RX            0x00001000
>>>> +#define MGMT_PHY_LE_CODED_TX 0x00002000
>>>> +#define MGMT_PHY_LE_CODED_RX 0x00004000
>>>> +
>>>> #define MGMT_EV_CMD_COMPLETE          0x0001
>>>> struct mgmt_ev_cmd_complete {
>>>>      __le16  opcode;
>>>> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
>>>> index 8a80d48..4a31d4d 100644
>>>> --- a/net/bluetooth/mgmt.c
>>>> +++ b/net/bluetooth/mgmt.c
>>>> @@ -617,6 +617,126 @@ static int read_config_info(struct sock *sk, str=
uct hci_dev *hdev,
>>>>                               &rp, sizeof(rp));
>>>> }
>>>>
>>>> +static u32 get_supported_phys(struct hci_dev *hdev)
>>>> +{
>>>> +     u32 supported_phys =3D 0;
>>>> +
>>>> +     if (lmp_bredr_capable(hdev)) {
>>>> +             supported_phys |=3D MGMT_PHY_BR_1M_1SLOT;
>>>> +
>>>> +             if (hdev->features[0][0] & LMP_3SLOT)
>>>> +                     supported_phys |=3D MGMT_PHY_BR_1M_3SLOT;
>>>> +
>>>> +             if (hdev->features[0][0] & LMP_5SLOT)
>>>> +                     supported_phys |=3D MGMT_PHY_BR_1M_5SLOT;
>>>> +
>>>> +             if (lmp_edr_2m_capable(hdev)) {
>>>> +                     supported_phys |=3D MGMT_PHY_EDR_2M_1SLOT;
>>>> +
>>>> +                     if (lmp_edr_3slot_capable(hdev))
>>>> +                             supported_phys |=3D MGMT_PHY_EDR_2M_3SLO=
T;
>>>> +
>>>> +                     if (lmp_edr_5slot_capable(hdev))
>>>> +                             supported_phys |=3D MGMT_PHY_EDR_2M_5SLO=
T;
>>>> +
>>>> +                     if (lmp_edr_3m_capable(hdev)) {
>>>> +                             supported_phys |=3D MGMT_PHY_EDR_3M_1SLO=
T;
>>>> +
>>>> +                             if (lmp_edr_3slot_capable(hdev))
>>>> +                                     supported_phys |=3D MGMT_PHY_EDR=
_3M_3SLOT;
>>>> +
>>>> +                             if (lmp_edr_5slot_capable(hdev))
>>>> +                                     supported_phys |=3D MGMT_PHY_EDR=
_3M_5SLOT;
>>>> +                     }
>>>> +             }
>>>> +     }
>>>> +
>>>> +     if (lmp_le_capable(hdev)) {
>>>> +             supported_phys |=3D MGMT_PHY_LE_1M_TX;
>>>> +             supported_phys |=3D MGMT_PHY_LE_1M_RX;
>>>> +
>>>> +             if (hdev->le_features[1] & HCI_LE_PHY_2M) {
>>>> +                     supported_phys |=3D MGMT_PHY_LE_2M_TX;
>>>> +                     supported_phys |=3D MGMT_PHY_LE_2M_RX;
>>>> +             }
>>>
>>> Extra empty line here.
>>>
>>>> +             if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
>>>> +                     supported_phys |=3D MGMT_PHY_LE_CODED_TX;
>>>> +                     supported_phys |=3D MGMT_PHY_LE_CODED_RX;
>>>> +             }
>>>> +     }
>>>> +
>>>> +     return supported_phys;
>>>> +}
>>>> +
>>>> +static u32 get_selected_phys(struct hci_dev *hdev)
>>>> +{
>>>> +     u32 selected_phys =3D 0;
>>>> +
>>>> +     if (lmp_bredr_capable(hdev)) {
>>>> +             selected_phys |=3D MGMT_PHY_BR_1M_1SLOT;
>>>> +
>>>> +             if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
>>>> +                     selected_phys |=3D MGMT_PHY_BR_1M_3SLOT;
>>>> +
>>>> +             if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
>>>> +                     selected_phys |=3D MGMT_PHY_BR_1M_5SLOT;
>>>> +
>>>> +             if (lmp_edr_2m_capable(hdev)) {
>>>> +                     if (!(hdev->pkt_type & HCI_2DH1))
>>>> +                             selected_phys |=3D MGMT_PHY_EDR_2M_1SLOT=
;
>>>> +
>>>> +                     if (lmp_edr_3slot_capable(hdev) &&
>>>> +                             !(hdev->pkt_type & HCI_2DH3))
>>>
>>> these need to align according to the netdev coding style.
>>>
>>>> +                             selected_phys |=3D MGMT_PHY_EDR_2M_3SLOT=
;
>>>> +
>>>> +                     if (lmp_edr_5slot_capable(hdev) &&
>>>> +                             !(hdev->pkt_type & HCI_2DH5))
>>>> +                             selected_phys |=3D MGMT_PHY_EDR_2M_5SLOT=
;
>>>> +
>>>> +                     if (lmp_edr_3m_capable(hdev)) {
>>>> +                             if (!(hdev->pkt_type & HCI_3DH1))
>>>> +                                     selected_phys |=3D MGMT_PHY_EDR_=
3M_1SLOT;
>>>> +
>>>> +                             if (lmp_edr_3slot_capable(hdev) &&
>>>> +                                     !(hdev->pkt_type & HCI_3DH3))
>>>> +                                     selected_phys |=3D MGMT_PHY_EDR_=
3M_3SLOT;
>>>> +
>>>> +                             if (lmp_edr_5slot_capable(hdev) &&
>>>> +                                     !(hdev->pkt_type & HCI_3DH5))
>>>> +                                     selected_phys |=3D MGMT_PHY_EDR_=
3M_5SLOT;
>>>> +                     }
>>>> +             }
>>>> +     }
>>>> +
>>>> +     if (lmp_le_capable(hdev)) {
>>>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
>>>> +                     selected_phys |=3D MGMT_PHY_LE_1M_TX;
>>>> +
>>>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
>>>> +                     selected_phys |=3D MGMT_PHY_LE_1M_RX;
>>>> +
>>>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
>>>> +                     selected_phys |=3D MGMT_PHY_LE_2M_TX;
>>>> +
>>>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
>>>> +                     selected_phys |=3D MGMT_PHY_LE_2M_RX;
>>>> +
>>>> +             if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
>>>> +                     selected_phys |=3D MGMT_PHY_LE_CODED_TX;
>>>> +
>>>> +             if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
>>>> +                     selected_phys |=3D MGMT_PHY_LE_CODED_RX;
>>>> +     }
>>>> +
>>>> +     return selected_phys;
>>>> +}
>>>> +
>>>> +static u32 get_configurable_phys(struct hci_dev *hdev)
>>>> +{
>>>> +     return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
>>>> +                     ~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
>>>
>>> Here the alignment needs to be also corrected.
>>>
>>>> +}
>>>> +
>>>> static u32 get_supported_settings(struct hci_dev *hdev)
>>>> {
>>>>      u32 settings =3D 0;
>>>> @@ -654,6 +774,10 @@ static u32 get_supported_settings(struct hci_dev =
*hdev)
>>>>          hdev->set_bdaddr)
>>>>              settings |=3D MGMT_SETTING_CONFIGURATION;
>>>>
>>>> +     if (get_supported_phys(hdev) & ~(MGMT_PHY_BR_1M_1SLOT | MGMT_PHY=
_LE_1M_TX |
>>>> +                                     MGMT_PHY_LE_1M_RX))
>>>
>>> Same here.
>>>
>>>> +             settings |=3D MGMT_SETTING_PHY_CONFIGURATION;
>>>> +
>>>
>>> Frankly I think that PHY configuration can be unconditionally be listed=
 as supported here. Even on a 4.0 or just a 1.2 device we should hint that =
PHY configuration is possible.
>>
>> If a controller supports only BR 1M 1 SLOT and / or only LE 1M then
>> PHY configuration should not be
>> set (which is what the check is doing).
>
> we could argue for that, but then I wonder if we are making of life more =
complicated than it needs to be. I currently see no value in this. I might =
have suggested something like that in the past, but I feel to see what valu=
e we have with that.
>
> If the PHY configuration setting is not present, then it is BR/EDR wild g=
uessing and LE 1M depending on the other settings bits. If PHY configuratio=
n set, then you use Get PHY configuration and know exactly. You will never =
try to interpret that setting bit anymore. You actually get the exact detai=
ls. So I would always just set it.
>
> I am open for reasons here, but I am failing to see the benefit of anythi=
ng complex at the moment.
>

I was actually thinking PHY_CONFIGURATION bit in Settings to let user know =
PHYs
can be configured (using SetPHYConfiguration) and GetPHYConfiguration
to be always
supported (which user can know from for eg SupportedCommands).

But since ConfigurablePHYs option is there in Get command its fine.

So i will make it unconditional in next patch.
>>
>>>
>>>>      return settings;
>>>> }
>>>>
>>>> @@ -722,6 +846,9 @@ static u32 get_current_settings(struct hci_dev *hd=
ev)
>>>>                      settings |=3D MGMT_SETTING_STATIC_ADDRESS;
>>>>      }
>>>>
>>>> +     if (phys_configured(hdev))
>>>> +             settings |=3D MGMT_SETTING_PHY_CONFIGURATION;
>>>> +
>>>
>>> What is this conditional doing? You need to add a comment here explaini=
ng when we set configuration flag in current settings and when not.
>>
>> This checks whether any PHY is deselected in BREDR or selected in LE.
>> Will add comment.
>>
>> So basically it will be set in supported settings if any PHYs other
>> than the basic PHYs is supported
>> and will set in current settings if any PHYs are configured
>> (deselected in BREDR or selected in LE).
>
> So for MGMT_SETTING_CONFIGURATION, we also never expose it in the current=
 settings, so until I figure out a need for this, we should not bother with=
 complex code for this either.
>
> We can really figure out later on how we use the current settings info of=
 the PHY configuration. Frankly, I have no idea what a default PHY config a=
ctually looks like with the combination of BR, BR/EDR, single vs dual and L=
E only controllers.
>
Ok, i will remove that in next patch.

Thanks,
Jaganath

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

* Re: [PATCH v4 07/13] Bluetooth: Read no of adv sets during init
  2018-07-16 13:18       ` Marcel Holtmann
@ 2018-07-16 13:51         ` Jaganath K
  0 siblings, 0 replies; 39+ messages in thread
From: Jaganath K @ 2018-07-16 13:51 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: open list:BLUETOOTH DRIVERS, Jaganath Kanakkassery

Hi Marcel,

On Mon, Jul 16, 2018 at 6:48 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Jaganath,
>
>>>> This patch reads the number of advertising sets in the controller
>>>> during init and save it in hdev.
>>>>
>>>> This also checks ext adv support before send Read Adv TX Power
>>>> since legacy and extended Adv commands should not be mixed.
>>>>
>>>> Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
>>>> ---
>>>> include/net/bluetooth/hci.h      |  7 +++++++
>>>> include/net/bluetooth/hci_core.h |  4 ++++
>>>> net/bluetooth/hci_core.c         | 12 ++++++++++--
>>>> net/bluetooth/hci_event.c        | 18 ++++++++++++++++++
>>>> 4 files changed, 39 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>>>> index fcd1d57..e584863 100644
>>>> --- a/include/net/bluetooth/hci.h
>>>> +++ b/include/net/bluetooth/hci.h
>>>> @@ -411,6 +411,7 @@ enum {
>>>> #define HCI_LE_SLAVE_FEATURES         0x08
>>>> #define HCI_LE_PING                   0x10
>>>> #define HCI_LE_DATA_LEN_EXT           0x20
>>>> +#define HCI_LE_EXT_ADV                       0x10
>>>> #define HCI_LE_EXT_SCAN_POLICY                0x80
>>>> #define HCI_LE_PHY_2M                 0x01
>>>> #define HCI_LE_PHY_CODED              0x08
>>>> @@ -1580,6 +1581,12 @@ struct hci_cp_le_ext_conn_param {
>>>>      __le16 max_ce_len;
>>>> } __packed;
>>>>
>>>> +#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS        0x203b
>>>> +struct hci_rp_le_read_num_supported_adv_sets {
>>>> +     __u8  status;
>>>> +     __u8  num_of_sets;
>>>> +} __packed;
>>>> +
>>>> /* ---- HCI Events ---- */
>>>> #define HCI_EV_INQUIRY_COMPLETE               0x01
>>>>
>>>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>>>> index 33aab89e..e845ca6 100644
>>>> --- a/include/net/bluetooth/hci_core.h
>>>> +++ b/include/net/bluetooth/hci_core.h
>>>> @@ -222,6 +222,7 @@ struct hci_dev {
>>>>      __u8            le_features[8];
>>>>      __u8            le_white_list_size;
>>>>      __u8            le_resolv_list_size;
>>>> +     __u8            le_no_of_adv_sets;
>>>
>>> I think our style was to use _num instead of _no. See num_iac for example.
>>>
>>>>      __u8            le_states[8];
>>>>      __u8            commands[64];
>>>>      __u8            hci_ver;
>>>> @@ -1180,6 +1181,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
>>>> /* Use ext create connection if command is supported */
>>>> #define use_ext_conn(dev) ((dev)->commands[37] & 0x80)
>>>>
>>>> +/* Extended advertising support */
>>>> +#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
>>>> +
>>>> /* ----- HCI protocols ----- */
>>>> #define HCI_PROTO_DEFER             0x01
>>>>
>>>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>>>> index 0d88dc9..b423587 100644
>>>> --- a/net/bluetooth/hci_core.c
>>>> +++ b/net/bluetooth/hci_core.c
>>>> @@ -715,8 +715,10 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
>>>>              hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
>>>>                          events);
>>>>
>>>> -             if (hdev->commands[25] & 0x40) {
>>>> -                     /* Read LE Advertising Channel TX Power */
>>>> +             if ((hdev->commands[25] & 0x40) && !ext_adv_capable(hdev)) {
>>>> +                     /* Read LE Advertising Channel TX Power only if
>>>> +                      * extended advertising is not supported
>>>> +                      */
>>>>                      hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
>>>>              }
>>>
>>> Why? I prefer that we read the adv TX power always. Even if we are not using it, it is good to have it in the traces.
>>
>> Mixing of legacy and extended commands is forbidden as per HCI TS spec
>> Please see  "HCI/GEV/BV-02-C [Disallow Mixing Legacy and Extended Advertising
>> Commands]"
>
> and that also includes the Read Adv TX Power command? That is totally strange and I wonder how that affects anything here.
>
> So is it that once you issued Read Adv TX Power you are no longer allowed to use ext adv commands? If that is really the case, then so be it, but this needs a larger comment in front of the if statement to explain what we are doing and why.
>

Yes, it includes Read Adv TX Power command and once it is issued
extended commands
cannot be used.

I will add larger comment for that.

Thanks,
Jaganath

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

end of thread, other threads:[~2018-07-16 13:51 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-11  9:31 [PATCH v4 00/13] Bluetooth: Extended Adv, Scan, Connection and PHY support Jaganath Kanakkassery
2018-07-11  9:31 ` [PATCH v4 01/13] Bluetooth: Define default phys in hdev and set 1M as default Jaganath Kanakkassery
2018-07-14 16:47   ` Marcel Holtmann
2018-07-11  9:31 ` [PATCH v4 02/13] Bluetooth: Implement Get PHY Configuration mgmt command Jaganath Kanakkassery
2018-07-14 17:00   ` Marcel Holtmann
2018-07-15  7:56     ` Jaganath K
2018-07-16 13:08       ` Marcel Holtmann
2018-07-16 13:46         ` Jaganath K
2018-07-11  9:31 ` [PATCH v4 03/13] Bluetooth: Implement Set PHY Confguration command Jaganath Kanakkassery
2018-07-14 17:18   ` Marcel Holtmann
2018-07-15  9:36     ` Jaganath K
2018-07-16 13:14       ` Marcel Holtmann
2018-07-11  9:31 ` [PATCH v4 04/13] Bluetooth: Set Scan PHYs based on selected PHYs by user Jaganath Kanakkassery
2018-07-14 17:24   ` Marcel Holtmann
2018-07-11  9:31 ` [PATCH v4 05/13] Bluetooth: Handle extended ADV PDU types Jaganath Kanakkassery
2018-07-14 17:28   ` Marcel Holtmann
2018-07-15  9:52     ` Jaganath K
2018-07-16 13:09       ` Marcel Holtmann
2018-07-11  9:31 ` [PATCH v4 06/13] Bluetooth: Use selected PHYs in extended connect Jaganath Kanakkassery
2018-07-14 17:30   ` Marcel Holtmann
2018-07-11  9:31 ` [PATCH v4 07/13] Bluetooth: Read no of adv sets during init Jaganath Kanakkassery
2018-07-14 17:32   ` Marcel Holtmann
2018-07-16  6:27     ` Jaganath K
2018-07-16 13:18       ` Marcel Holtmann
2018-07-16 13:51         ` Jaganath K
2018-07-11  9:31 ` [PATCH v4 08/13] Bluetooth: Impmlement extended adv enable Jaganath Kanakkassery
2018-07-14 18:38   ` Marcel Holtmann
2018-07-16  8:12     ` Jaganath K
2018-07-11  9:31 ` [PATCH v4 09/13] Bluetooth: Use Set ext adv/scan rsp data if controller supports Jaganath Kanakkassery
2018-07-14 18:47   ` Marcel Holtmann
2018-07-11  9:31 ` [PATCH v4 10/13] Bluetooth: Implement disable and removal of adv instance Jaganath Kanakkassery
2018-07-14 18:50   ` Marcel Holtmann
2018-07-16  8:21     ` Jaganath K
2018-07-11  9:31 ` [PATCH v4 11/13] Bluetooth: Use ext adv for directed adv Jaganath Kanakkassery
2018-07-14 18:56   ` Marcel Holtmann
2018-07-11  9:31 ` [PATCH v4 12/13] Bluetooth: Implement Set ADV set random address Jaganath Kanakkassery
2018-07-14 20:52   ` Marcel Holtmann
2018-07-16  9:57     ` Jaganath K
2018-07-11  9:31 ` [PATCH v4 13/13] Bluetooth: Implement secondary advertising on different PHYs Jaganath Kanakkassery

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.