Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC 9/9] Bluetooth: Add set observer MGMT command
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

This command will enable or disable observer mode.

If LE_ENABLED is set the HCI_OP_LE_SET_SCAN_PARAMS and HCI_OP_LE_SET_SCAN_ENABLE
commands will be sent. Observer will perform a passive scan with no timeout.

If discovery is required when observer is enabled, le scan is restarted in
active mode.

If observer is enabled when discovery finishes, passive le scan
is enabled.

If observer mode is required when discovery is on going, the le scan mode does
not change until the end of discovery process.

This command is available on the powered off state.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci.h      |    1 +
 include/net/bluetooth/hci_core.h |    5 ++
 include/net/bluetooth/mgmt.h     |    3 +
 net/bluetooth/hci_core.c         |   18 ++++-
 net/bluetooth/hci_event.c        |   50 ++++++------
 net/bluetooth/mgmt.c             |  165 ++++++++++++++++++++++++++++++++++----
 6 files changed, 201 insertions(+), 41 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 591450c..78538c0 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -121,6 +121,7 @@ enum {
 	HCI_PENDING_CLASS,
 	HCI_PERIODIC_INQ,
 	HCI_BROADCASTER,
+	HCI_OBSERVER,
 };
 
 /* HCI ioctl defines */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6ef8660..f6bab83 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -55,6 +55,8 @@ struct inquiry_entry {
 	struct inquiry_data	data;
 };
 
+#define hdev_is_in_discovery(hdev) (hdev->discovery.state != DISCOVERY_STOPPED)
+
 struct discovery_state {
 	int			type;
 	enum {
@@ -133,7 +135,9 @@ struct controller_data {
 };
 
 enum {
+	LE_SCAN_REQ_REASON_RESET,
 	LE_SCAN_REQ_REASON_DISCOVERY,
+	LE_SCAN_REQ_REASON_OBSERVER,
 };
 
 #define HCI_MAX_SHORT_NAME_LENGTH	10
@@ -1095,6 +1099,7 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
 					    u8 *randomizer, u8 status);
 int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
 int mgmt_set_broadcaster_complete(struct hci_dev *hdev, u8 enable, u8 status);
+int mgmt_set_observer_complete(struct hci_dev *hdev, u8 enable, u8 status);
 int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		      u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
 		      u8 ssp, u8 *eir, u16 eir_len);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index bd64816..13936ab 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -93,6 +93,7 @@ struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_HS			0x00000100
 #define MGMT_SETTING_LE			0x00000200
 #define MGMT_SETTING_BROADCASTER	0x00000400
+#define MGMT_SETTING_OBSERVER		0x00000800
 
 #define MGMT_OP_READ_INFO		0x0004
 #define MGMT_READ_INFO_SIZE		0
@@ -368,6 +369,8 @@ struct mgmt_cp_unset_controller_data {
 
 #define MGMT_OP_SET_BROADCASTER		0x002B
 
+#define MGMT_OP_SET_OBSERVER		0x002C
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index fbf0ba1..1482681 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1556,14 +1556,28 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
 
 	BT_DBG("%s", hdev->name);
 
-	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
+	    reason == LE_SCAN_REQ_REASON_OBSERVER)
 		return -EINPROGRESS;
 
+	memset(&cp, 0, sizeof(cp));
+
+	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
+	    reason == LE_SCAN_REQ_REASON_DISCOVERY) {
+		hci_dev_lock(hdev);
+		hdev->le_scan_req_reason = LE_SCAN_REQ_REASON_RESET;
+		hci_dev_unlock(hdev);
+
+		err = hci_request(hdev, le_scan_enable_req, (unsigned long) &cp,
+				  timeo);
+		if (err)
+			return err;
+	}
+
 	param.type = type;
 	param.interval = interval;
 	param.window = window;
 
-	memset(&cp, 0, sizeof(cp));
 	cp.enable = 1;
 	if (reason == LE_SCAN_REQ_REASON_DISCOVERY)
 		cp.filter_dup = 1;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 7ad2b0d..f31b694 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1212,42 +1212,42 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 	if (!cp)
 		return;
 
-	switch (cp->enable) {
-	case LE_SCANNING_ENABLED:
-		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
+	hci_dev_lock(hdev);
 
-		if (status) {
-			hci_dev_lock(hdev);
-			mgmt_start_discovery_failed(hdev, status);
-			hci_dev_unlock(hdev);
-			return;
-		}
+	if (!status) {
+		if (cp->enable)
+			set_bit(HCI_LE_SCAN, &hdev->dev_flags);
+		else
+			clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
+	}
 
-		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
+	if (hdev->le_scan_req_reason == LE_SCAN_REQ_REASON_RESET)
+		goto unlock;
 
-		hci_dev_lock(hdev);
-		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
-		hci_dev_unlock(hdev);
+	if (hdev->le_scan_req_reason == LE_SCAN_REQ_REASON_OBSERVER) {
+		mgmt_set_observer_complete(hdev, cp->enable, status);
+		goto unlock;
+	}
+
+	switch (cp->enable) {
+	case LE_SCANNING_ENABLED:
+		if (status)
+			mgmt_start_discovery_failed(hdev, status);
+		else
+			hci_discovery_set_state(hdev, DISCOVERY_FINDING);
 		break;
 
 	case LE_SCANNING_DISABLED:
 		if (status) {
-			hci_dev_lock(hdev);
 			mgmt_stop_discovery_failed(hdev, status);
-			hci_dev_unlock(hdev);
-			return;
+			goto unlock;
 		}
 
-		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
-
 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
-		    hdev->discovery.state == DISCOVERY_FINDING) {
+		    hdev->discovery.state == DISCOVERY_FINDING)
 			mgmt_interleaved_discovery(hdev);
-		} else {
-			hci_dev_lock(hdev);
+		else
 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
-			hci_dev_unlock(hdev);
-		}
 
 		break;
 
@@ -1255,6 +1255,10 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
 		break;
 	}
+
+unlock:
+	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
+	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 46a45e7..bd7b238 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -106,11 +106,13 @@ static const u16 mgmt_events[] = {
  * These LE scan and inquiry parameters were chosen according to LE General
  * Discovery Procedure specification.
  */
-#define LE_SCAN_TYPE			0x01
+#define LE_SCAN_TYPE_PASSIVE		0x00
+#define LE_SCAN_TYPE_ACTIVE		0x01
 #define LE_SCAN_WIN			0x12
 #define LE_SCAN_INT			0x12
 #define LE_SCAN_TIMEOUT_LE_ONLY		10240	/* TGAP(gen_disc_scan_min) */
 #define LE_SCAN_TIMEOUT_BREDR_LE	5120	/* TGAP(100)/2 */
+#define LE_SCAN_NO_TIMEOUT		-1	/* Observer role */
 
 #define INQUIRY_LEN_BREDR		0x08	/* TGAP(100) */
 #define INQUIRY_LEN_BREDR_LE		0x04	/* TGAP(100)/2 */
@@ -381,6 +383,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
 	settings |= MGMT_SETTING_DISCOVERABLE;
 	settings |= MGMT_SETTING_PAIRABLE;
 	settings |= MGMT_SETTING_BROADCASTER;
+	settings |= MGMT_SETTING_OBSERVER;
 
 	if (lmp_ssp_capable(hdev))
 		settings |= MGMT_SETTING_SSP;
@@ -424,6 +427,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
 	if (test_bit(HCI_BROADCASTER, &hdev->dev_flags))
 		settings |= MGMT_SETTING_BROADCASTER;
 
+	if (test_bit(HCI_OBSERVER, &hdev->dev_flags))
+		settings |= MGMT_SETTING_OBSERVER;
+
 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
 		settings |= MGMT_SETTING_LINK_SECURITY;
 
@@ -2305,14 +2311,10 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev)
 
 	BT_DBG("%s", hdev->name);
 
-	hci_dev_lock(hdev);
-
 	err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE);
 	if (err < 0)
 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
 
-	hci_dev_unlock(hdev);
-
 	return err;
 }
 
@@ -2339,7 +2341,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 		goto failed;
 	}
 
-	if (hdev->discovery.state != DISCOVERY_STOPPED) {
+	if (hdev_is_in_discovery(hdev)) {
 		err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
 				 MGMT_STATUS_BUSY);
 		goto failed;
@@ -2363,8 +2365,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 
 	case DISCOV_TYPE_LE:
 		if (lmp_host_le_capable(hdev))
-			err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
-					  LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY,
+			err = hci_le_scan(hdev, LE_SCAN_TYPE_ACTIVE,
+					  LE_SCAN_INT, LE_SCAN_WIN,
+					  LE_SCAN_TIMEOUT_LE_ONLY,
 					  LE_SCAN_REQ_REASON_DISCOVERY);
 		else
 			err = -ENOTSUPP;
@@ -2372,8 +2375,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 
 	case DISCOV_TYPE_INTERLEAVED:
 		if (lmp_host_le_capable(hdev) && lmp_bredr_capable(hdev))
-			err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
-					  LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE,
+			err = hci_le_scan(hdev, LE_SCAN_TYPE_ACTIVE,
+					  LE_SCAN_INT, LE_SCAN_WIN,
+					  LE_SCAN_TIMEOUT_BREDR_LE,
 					  LE_SCAN_REQ_REASON_DISCOVERY);
 		else
 			err = -ENOTSUPP;
@@ -2850,6 +2854,89 @@ static int set_broadcaster(struct sock *sk, struct hci_dev *hdev, void *data,
 	return set_broadcaster_le(sk, hdev, cp->val);
 }
 
+static int set_observer_le(struct sock *sk, struct hci_dev *hdev, u8 enable)
+{
+	struct pending_cmd *cmd;
+	int err;
+
+	BT_DBG("%s enable:%i", hdev->name, enable);
+
+	hci_dev_lock(hdev);
+
+	if (!hdev_is_powered(hdev)) {
+		bool changed = false;
+
+		if (enable != test_bit(HCI_OBSERVER, &hdev->dev_flags)) {
+			change_bit(HCI_OBSERVER, &hdev->dev_flags);
+			changed = true;
+		}
+
+		err = send_settings_rsp(sk, MGMT_OP_SET_OBSERVER, hdev);
+		if (err < 0)
+			goto unlock;
+
+		if (changed)
+			err = new_settings(hdev, sk);
+
+		goto unlock;
+	}
+
+	if (mgmt_pending_find(MGMT_OP_SET_OBSERVER, hdev)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_OBSERVER,
+				 MGMT_STATUS_BUSY);
+		goto unlock;
+	}
+
+	if (enable == test_bit(HCI_OBSERVER, &hdev->dev_flags)) {
+		err = send_settings_rsp(sk, MGMT_OP_SET_OBSERVER, hdev);
+		goto unlock;
+	}
+
+	if (hdev_is_in_discovery(hdev)) {
+		change_bit(HCI_OBSERVER, &hdev->dev_flags);
+		err = send_settings_rsp(sk, MGMT_OP_SET_OBSERVER, hdev);
+		if (err < 0)
+			goto unlock;
+
+		err = new_settings(hdev, sk);
+		goto unlock;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_OBSERVER, hdev, NULL, 0);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto unlock;
+	}
+
+	if (enable)
+		err = hci_le_scan(hdev, LE_SCAN_TYPE_PASSIVE, LE_SCAN_INT,
+				  LE_SCAN_WIN, LE_SCAN_NO_TIMEOUT,
+				  LE_SCAN_REQ_REASON_OBSERVER);
+	else
+		err = hci_cancel_le_scan(hdev, LE_SCAN_REQ_REASON_OBSERVER);
+
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+	return err;
+}
+
+static int set_observer(struct sock *sk, struct hci_dev *hdev, void *data,
+			u16 len)
+{
+	struct mgmt_mode *cp = data;
+
+	BT_DBG("%s val:%i", hdev->name, cp->val);
+
+	if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_OBSERVER,
+				  MGMT_STATUS_NOT_SUPPORTED);
+
+	return set_observer_le(sk, hdev, cp->val);
+}
+
 static const struct mgmt_handler {
 	int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
 		     u16 data_len);
@@ -2900,6 +2987,7 @@ static const struct mgmt_handler {
 	{ set_controller_data,    true,  MGMT_SET_CONTROLLER_DATA_SIZE },
 	{ unset_controller_data,  false, MGMT_UNSET_CONTROLLER_DATA_SIZE },
 	{ set_broadcaster,        false, MGMT_SETTING_SIZE },
+	{ set_observer,           false, MGMT_SETTING_SIZE },
 };
 
 
@@ -3080,14 +3168,19 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
 		update_name(hdev, hdev->dev_name);
 		update_eir(hdev);
 
-		if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+		if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
 			update_adv_data(hdev);
 
-		if (test_bit(HCI_BROADCASTER, &hdev->dev_flags) &&
-		    test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
-			u8 enable = 1;
-			hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE,
-				     sizeof(enable), &enable);
+			if (test_bit(HCI_BROADCASTER, &hdev->dev_flags)) {
+				u8 enable = 1;
+				hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE,
+					     sizeof(enable), &enable);
+			} else if (test_bit(HCI_OBSERVER, &hdev->dev_flags)) {
+				hci_le_scan(hdev, LE_SCAN_TYPE_PASSIVE,
+					  LE_SCAN_INT,
+					  LE_SCAN_WIN, LE_SCAN_NO_TIMEOUT,
+					  LE_SCAN_REQ_REASON_OBSERVER);
+			}
 		}
 
 	} else {
@@ -3782,6 +3875,41 @@ int mgmt_set_broadcaster_complete(struct hci_dev *hdev, u8 enable, u8 status)
 	return err;
 }
 
+int mgmt_set_observer_complete(struct hci_dev *hdev, u8 enable, u8 status)
+{
+	struct cmd_lookup match = { NULL, hdev };
+	bool changed = false;
+	int err = 0;
+
+	if (status) {
+		u8 mgmt_err = mgmt_status(status);
+
+		mgmt_pending_foreach(MGMT_OP_SET_OBSERVER, hdev,
+				     cmd_status_rsp, &mgmt_err);
+
+		return err;
+	}
+
+	if (enable) {
+		if (!test_and_set_bit(HCI_OBSERVER, &hdev->dev_flags))
+			changed = true;
+	} else {
+		if (test_and_clear_bit(HCI_OBSERVER, &hdev->dev_flags))
+			changed = true;
+	}
+
+	mgmt_pending_foreach(MGMT_OP_SET_OBSERVER, hdev, settings_rsp,
+			     &match);
+
+	if (changed)
+		err = new_settings(hdev, match.sk);
+
+	if (match.sk)
+		sock_put(match.sk);
+
+	return err;
+}
+
 int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		      u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
 		      ssp, u8 *eir, u16 eir_len)
@@ -3898,6 +4026,11 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering)
 		mgmt_pending_remove(cmd);
 	}
 
+	if (!discovering && test_bit(HCI_OBSERVER, &hdev->dev_flags))
+		hci_le_scan(hdev, LE_SCAN_TYPE_PASSIVE, LE_SCAN_INT,
+			    LE_SCAN_WIN, LE_SCAN_NO_TIMEOUT,
+			    LE_SCAN_REQ_REASON_OBSERVER);
+
 	memset(&ev, 0, sizeof(ev));
 	ev.type = hdev->discovery.type;
 	ev.discovering = discovering;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 8/9] Bluetooth: Refactor le scan helpers to enable observer support
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

It was added a parameter called 'reason' to le scan helpers (hci_do_le_scan and
hci_cancel_le_scan). Distinguishing the reason to enbale/disable le scan will be
important when both discovery and observer are implemented.

'reason' was also added do hdev structure (hdev.le_scan_req_reason) in order
to make hci_cc_le_set_scan_enable behave correctly.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci_core.h |   11 +++++--
 net/bluetooth/hci_core.c         |   63 +++++++++++++++++++++++---------------
 net/bluetooth/mgmt.c             |   10 +++---
 3 files changed, 54 insertions(+), 30 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index fc26210..6ef8660 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -121,6 +121,7 @@ struct le_scan_params {
 	u16 interval;
 	u16 window;
 	int timeout;
+	u8 reason;
 };
 
 struct controller_data {
@@ -131,6 +132,10 @@ struct controller_data {
 	u8 data[0];
 };
 
+enum {
+	LE_SCAN_REQ_REASON_DISCOVERY,
+};
+
 #define HCI_MAX_SHORT_NAME_LENGTH	10
 
 struct amp_assoc {
@@ -285,6 +290,7 @@ struct hci_dev {
 
 	struct work_struct	le_scan;
 	struct le_scan_params	le_scan_params;
+	__u8			le_scan_req_reason;
 
 	__s8			adv_tx_power;
 
@@ -1139,9 +1145,10 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
 							__u8 ltk[16]);
 int hci_do_inquiry(struct hci_dev *hdev, u8 length);
 int hci_cancel_inquiry(struct hci_dev *hdev);
+
 int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
-		int timeout);
-int hci_cancel_le_scan(struct hci_dev *hdev);
+		int timeout, u8 reason);
+int hci_cancel_le_scan(struct hci_dev *hdev, u8 reason);
 
 u8 bdaddr_to_le(u8 bdaddr_type);
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2c2f3aa..fbf0ba1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1538,20 +1538,20 @@ static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt)
 
 static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt)
 {
-	struct hci_cp_le_set_scan_enable cp;
+	struct hci_cp_le_set_scan_enable *cp;
 
-	memset(&cp, 0, sizeof(cp));
-	cp.enable = 1;
-	cp.filter_dup = 1;
+	cp = (struct hci_cp_le_set_scan_enable *) opt;
 
-	hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+	hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
+		     sizeof(struct hci_cp_le_set_scan_enable), cp);
 }
 
 static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
-			  u16 window, int timeout)
+			  u16 window, int timeout, u8 reason)
 {
 	long timeo = msecs_to_jiffies(3000);
 	struct le_scan_params param;
+	struct hci_cp_le_set_scan_enable cp;
 	int err;
 
 	BT_DBG("%s", hdev->name);
@@ -1563,38 +1563,52 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
 	param.interval = interval;
 	param.window = window;
 
+	memset(&cp, 0, sizeof(cp));
+	cp.enable = 1;
+	if (reason == LE_SCAN_REQ_REASON_DISCOVERY)
+		cp.filter_dup = 1;
+
+	hci_dev_lock(hdev);
+	hdev->le_scan_req_reason = reason;
+	hci_dev_unlock(hdev);
+
 	hci_req_lock(hdev);
 
 	err = __hci_request(hdev, le_scan_param_req, (unsigned long) &param,
 			    timeo);
-	if (!err)
-		err = __hci_request(hdev, le_scan_enable_req, 0, timeo);
+	if (err)
+		goto unlock;
 
-	hci_req_unlock(hdev);
-
-	if (err < 0)
-		return err;
+	err = __hci_request(hdev, le_scan_enable_req, (unsigned long) &cp,
+			    timeo);
+	if (err)
+		goto unlock;
 
-	schedule_delayed_work(&hdev->le_scan_disable,
-			      msecs_to_jiffies(timeout));
+	if (timeout > 0)
+		schedule_delayed_work(&hdev->le_scan_disable,
+				      msecs_to_jiffies(timeout));
 
-	return 0;
+unlock:
+	hci_req_unlock(hdev);
+	return err;
 }
 
-int hci_cancel_le_scan(struct hci_dev *hdev)
+int hci_cancel_le_scan(struct hci_dev *hdev, u8 reason)
 {
+	struct hci_cp_le_set_scan_enable cp;
+
 	BT_DBG("%s", hdev->name);
 
 	if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
 		return -EALREADY;
 
-	if (cancel_delayed_work(&hdev->le_scan_disable)) {
-		struct hci_cp_le_set_scan_enable cp;
+	if (reason == LE_SCAN_REQ_REASON_DISCOVERY)
+		if (!cancel_delayed_work(&hdev->le_scan_disable))
+			return 0;
 
-		/* Send HCI command to disable LE Scan */
-		memset(&cp, 0, sizeof(cp));
-		hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
-	}
+	/* Send HCI command to disable LE Scan */
+	memset(&cp, 0, sizeof(cp));
+	hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
 
 	return 0;
 }
@@ -1620,11 +1634,11 @@ static void le_scan_work(struct work_struct *work)
 	BT_DBG("%s", hdev->name);
 
 	hci_do_le_scan(hdev, param->type, param->interval, param->window,
-		       param->timeout);
+		       param->timeout, param->reason);
 }
 
 int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
-		int timeout)
+		int timeout, u8 reason)
 {
 	struct le_scan_params *param = &hdev->le_scan_params;
 
@@ -1637,6 +1651,7 @@ int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
 	param->interval = interval;
 	param->window = window;
 	param->timeout = timeout;
+	param->reason = reason;
 
 	queue_work(system_long_wq, &hdev->le_scan);
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 705859f..46a45e7 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2364,7 +2364,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 	case DISCOV_TYPE_LE:
 		if (lmp_host_le_capable(hdev))
 			err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
-					  LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
+					  LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY,
+					  LE_SCAN_REQ_REASON_DISCOVERY);
 		else
 			err = -ENOTSUPP;
 		break;
@@ -2372,8 +2373,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 	case DISCOV_TYPE_INTERLEAVED:
 		if (lmp_host_le_capable(hdev) && lmp_bredr_capable(hdev))
 			err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
-					  LE_SCAN_WIN,
-					  LE_SCAN_TIMEOUT_BREDR_LE);
+					  LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE,
+					  LE_SCAN_REQ_REASON_DISCOVERY);
 		else
 			err = -ENOTSUPP;
 		break;
@@ -2430,7 +2431,8 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
 		if (test_bit(HCI_INQUIRY, &hdev->flags))
 			err = hci_cancel_inquiry(hdev);
 		else
-			err = hci_cancel_le_scan(hdev);
+			err = hci_cancel_le_scan(hdev,
+						 LE_SCAN_REQ_REASON_DISCOVERY);
 
 		break;
 
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 7/9] Bluetooth: Add set broadcaster MGMT command
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

This command will enable or disable broadcaster mode. Data can be added
with set_controller_data command.

If LE_ENABLED is set, the HCI_OP_LE_SET_ADV_ENABLE command will be sent.

This command is available on the powered off state.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci.h      |    1 +
 include/net/bluetooth/hci_core.h |    1 +
 include/net/bluetooth/mgmt.h     |    3 +
 net/bluetooth/hci_event.c        |   21 +++++++
 net/bluetooth/mgmt.c             |  116 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 142 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 1dadf3d..591450c 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -120,6 +120,7 @@ enum {
 	HCI_LINK_SECURITY,
 	HCI_PENDING_CLASS,
 	HCI_PERIODIC_INQ,
+	HCI_BROADCASTER,
 };
 
 /* HCI ioctl defines */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d5d4dc4..fc26210 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1088,6 +1088,7 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
 int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
 					    u8 *randomizer, u8 status);
 int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
+int mgmt_set_broadcaster_complete(struct hci_dev *hdev, u8 enable, u8 status);
 int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		      u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
 		      u8 ssp, u8 *eir, u16 eir_len);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index bbb4b4a..bd64816 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -92,6 +92,7 @@ struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_BREDR		0x00000080
 #define MGMT_SETTING_HS			0x00000100
 #define MGMT_SETTING_LE			0x00000200
+#define MGMT_SETTING_BROADCASTER	0x00000400
 
 #define MGMT_OP_READ_INFO		0x0004
 #define MGMT_READ_INFO_SIZE		0
@@ -365,6 +366,8 @@ struct mgmt_cp_unset_controller_data {
 } __packed;
 #define MGMT_UNSET_CONTROLLER_DATA_SIZE	1
 
+#define MGMT_OP_SET_BROADCASTER		0x002B
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3df6e67..7ad2b0d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1330,6 +1330,23 @@ static void hci_cc_le_set_adv_params(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_req_complete(hdev, HCI_OP_LE_SET_ADV_PARAMS, status);
 }
 
+static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status = *((__u8 *) skb->data);
+	__u8 enable;
+	void *sent;
+
+	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
+	if (!sent)
+		return;
+
+	enable = *((__u8 *) sent);
+
+	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
+	    !test_bit(HCI_INIT, &hdev->flags))
+		mgmt_set_broadcaster_complete(hdev, enable, status);
+}
+
 static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -2593,6 +2610,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_le_set_adv_params(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_ADV_ENABLE:
+		hci_cc_le_set_adv_enable(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a094ef3..705859f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -380,6 +380,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
 	settings |= MGMT_SETTING_FAST_CONNECTABLE;
 	settings |= MGMT_SETTING_DISCOVERABLE;
 	settings |= MGMT_SETTING_PAIRABLE;
+	settings |= MGMT_SETTING_BROADCASTER;
 
 	if (lmp_ssp_capable(hdev))
 		settings |= MGMT_SETTING_SSP;
@@ -420,6 +421,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
 		settings |= MGMT_SETTING_LE;
 
+	if (test_bit(HCI_BROADCASTER, &hdev->dev_flags))
+		settings |= MGMT_SETTING_BROADCASTER;
+
 	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
 		settings |= MGMT_SETTING_LINK_SECURITY;
 
@@ -2776,6 +2780,74 @@ static int unset_controller_data(struct sock *sk, struct hci_dev *hdev,
 			    NULL, 0);
 }
 
+static int set_broadcaster_le(struct sock *sk, struct hci_dev *hdev, u8 enable)
+{
+	struct pending_cmd *cmd;
+	int err;
+
+	BT_DBG("%s enable:%i", hdev->name, enable);
+
+	hci_dev_lock(hdev);
+
+	if (!hdev_is_powered(hdev)) {
+		bool changed = false;
+
+		if (enable != test_bit(HCI_BROADCASTER, &hdev->dev_flags)) {
+			change_bit(HCI_BROADCASTER, &hdev->dev_flags);
+			changed = true;
+		}
+
+		err = send_settings_rsp(sk, MGMT_OP_SET_BROADCASTER, hdev);
+		if (err < 0)
+			goto unlock;
+
+		if (changed)
+			err = new_settings(hdev, sk);
+
+		goto unlock;
+	}
+
+	if (enable == test_bit(HCI_BROADCASTER, &hdev->dev_flags)) {
+		err = send_settings_rsp(sk, MGMT_OP_SET_BROADCASTER, hdev);
+		goto unlock;
+	}
+
+	if (mgmt_pending_find(MGMT_OP_SET_BROADCASTER, hdev)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_BROADCASTER,
+				 MGMT_STATUS_BUSY);
+		goto unlock;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_BROADCASTER, hdev, NULL, 0);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto unlock;
+	}
+
+	err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
+			   &enable);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+	return err;
+}
+
+static int set_broadcaster(struct sock *sk, struct hci_dev *hdev, void *data,
+			   u16 len)
+{
+	struct mgmt_mode *cp = data;
+
+	BT_DBG("%s val:%i", hdev->name, cp->val);
+
+	if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_BROADCASTER,
+				  MGMT_STATUS_NOT_SUPPORTED);
+
+	return set_broadcaster_le(sk, hdev, cp->val);
+}
+
 static const struct mgmt_handler {
 	int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
 		     u16 data_len);
@@ -2825,6 +2897,7 @@ static const struct mgmt_handler {
 	{ set_device_id,          false, MGMT_SET_DEVICE_ID_SIZE },
 	{ set_controller_data,    true,  MGMT_SET_CONTROLLER_DATA_SIZE },
 	{ unset_controller_data,  false, MGMT_UNSET_CONTROLLER_DATA_SIZE },
+	{ set_broadcaster,        false, MGMT_SETTING_SIZE },
 };
 
 
@@ -3007,6 +3080,14 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
 
 		if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
 			update_adv_data(hdev);
+
+		if (test_bit(HCI_BROADCASTER, &hdev->dev_flags) &&
+		    test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+			u8 enable = 1;
+			hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE,
+				     sizeof(enable), &enable);
+		}
+
 	} else {
 		u8 status = MGMT_STATUS_NOT_POWERED;
 		mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
@@ -3664,6 +3745,41 @@ int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
 	return err;
 }
 
+int mgmt_set_broadcaster_complete(struct hci_dev *hdev, u8 enable, u8 status)
+{
+	struct cmd_lookup match = { NULL, hdev };
+	bool changed = false;
+	int err = 0;
+
+	if (status) {
+		u8 mgmt_err = mgmt_status(status);
+
+		mgmt_pending_foreach(MGMT_OP_SET_BROADCASTER, hdev,
+				     cmd_status_rsp, &mgmt_err);
+
+		return err;
+	}
+
+	if (enable) {
+		if (!test_and_set_bit(HCI_BROADCASTER, &hdev->dev_flags))
+			changed = true;
+	} else {
+		if (test_and_clear_bit(HCI_BROADCASTER, &hdev->dev_flags))
+			changed = true;
+	}
+
+	mgmt_pending_foreach(MGMT_OP_SET_BROADCASTER, hdev, settings_rsp,
+			     &match);
+
+	if (changed)
+		err = new_settings(hdev, match.sk);
+
+	if (match.sk)
+		sock_put(match.sk);
+
+	return err;
+}
+
 int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		      u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
 		      ssp, u8 *eir, u16 eir_len)
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 6/9] Bluetooth: Add HCI command to enable/disable advertising
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes, Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

This command will be used when in discoverable mode or broadcaster role.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci.h |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index c0e9c3f..1dadf3d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -963,6 +963,10 @@ struct hci_cp_le_set_adv_data {
 	__u8     data[HCI_MAX_ADV_LENGTH];
 } __packed;
 
+#define HCI_OP_LE_SET_ADV_ENABLE	0x200a
+	#define ADVERTISING_DISABLE	0x00
+	#define ADVERTISING_ENABLE	0x01
+
 #define HCI_OP_LE_SET_SCAN_PARAM	0x200b
 struct hci_cp_le_set_scan_param {
 	__u8    type;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 5/9] Bluetooth: Add unset controller data MGMT command
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes, Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Unset controller data allows user to remove some data previously set to be
advertised via set controller data MGMT command.

If LE_ENABLED is set, the HCI_OP_LE_SET_ADV_DATA command will be sent.

This command is available on the powered off state.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci_core.h |    1 +
 include/net/bluetooth/mgmt.h     |    6 ++++++
 net/bluetooth/hci_core.c         |   19 +++++++++++++++++++
 net/bluetooth/mgmt.c             |   22 ++++++++++++++++++++++
 4 files changed, 48 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4046111..d5d4dc4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -761,6 +761,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 int hci_controller_data_add(struct hci_dev *hdev, u8 flags, u8 type, u8 length,
 			    u8 *data);
 int hci_controller_data_clear(struct hci_dev *hdev);
+int hci_controller_data_remove(struct hci_dev *hdev, u8 type);
 
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
 
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index f99e0a8..bbb4b4a 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -359,6 +359,12 @@ struct mgmt_cp_set_controller_data {
 } __packed;
 #define MGMT_SET_CONTROLLER_DATA_SIZE	3
 
+#define MGMT_OP_UNSET_CONTROLLER_DATA	0x002A
+struct mgmt_cp_unset_controller_data {
+	__u8	type;
+} __packed;
+#define MGMT_UNSET_CONTROLLER_DATA_SIZE	1
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e5ab961..2c2f3aa 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1439,6 +1439,25 @@ int hci_controller_data_clear(struct hci_dev *hdev)
 	return 0;
 }
 
+int hci_controller_data_remove(struct hci_dev *hdev, u8 type)
+{
+	struct controller_data *match, *n;
+	int matches = 0;
+
+	list_for_each_entry_safe(match, n, &hdev->controller_data, list) {
+		if (type != match->type)
+			continue;
+
+		list_del(&match->list);
+		hdev->adv_data_len -= sizeof(match->length) +
+				      sizeof(match->type) + match->length;
+		kfree(match);
+		matches++;
+	}
+
+	return matches;
+}
+
 struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 	struct bdaddr_list *b;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1ada019..a094ef3 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2755,6 +2755,27 @@ static int set_controller_data(struct sock *sk, struct hci_dev *hdev,
 			    0);
 }
 
+static int unset_controller_data(struct sock *sk, struct hci_dev *hdev,
+				 void *data, u16 len)
+{
+	struct mgmt_cp_unset_controller_data *cp = data;
+	int removed;
+
+	BT_DBG("%s type:0x%02x", hdev->name, cp->type);
+
+	hci_dev_lock(hdev);
+
+	removed = hci_controller_data_remove(hdev, cp->type);
+
+	if (removed && test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+		update_adv_data(hdev);
+
+	hci_dev_unlock(hdev);
+
+	return cmd_complete(sk, hdev->id, MGMT_OP_UNSET_CONTROLLER_DATA, 0,
+			    NULL, 0);
+}
+
 static const struct mgmt_handler {
 	int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
 		     u16 data_len);
@@ -2803,6 +2824,7 @@ static const struct mgmt_handler {
 	{ unblock_device,         false, MGMT_UNBLOCK_DEVICE_SIZE },
 	{ set_device_id,          false, MGMT_SET_DEVICE_ID_SIZE },
 	{ set_controller_data,    true,  MGMT_SET_CONTROLLER_DATA_SIZE },
+	{ unset_controller_data,  false, MGMT_UNSET_CONTROLLER_DATA_SIZE },
 };
 
 
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 4/9] Bluetooth: Add set controller data MGMT command
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

Set controller data allows user to set advertising data. The available data
types are 'service data' and 'manufacturer specific data'.

If LE_ENABLED is set, the HCI_OP_LE_SET_ADV_DATA command will be sent.

This command is available on the powered off state.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci.h      |    3 ++
 include/net/bluetooth/hci_core.h |   15 ++++++++
 include/net/bluetooth/mgmt.h     |    9 +++++
 net/bluetooth/hci_core.c         |   36 +++++++++++++++++++
 net/bluetooth/mgmt.c             |   74 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 137 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 75b7e58..c0e9c3f 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -333,6 +333,9 @@ enum {
 #define EIR_SSP_HASH_C		0x0E /* Simple Pairing Hash C */
 #define EIR_SSP_RAND_R		0x0F /* Simple Pairing Randomizer R */
 #define EIR_DEVICE_ID		0x10 /* device ID */
+/* Advertising field types */
+#define ADV_SERVICE_DATA	0x16 /* Service Data */
+#define ADV_MANUFACTURER_DATA	0xFF /* Manufacturer Specific Data */
 
 /* -----  HCI Commands ---- */
 #define HCI_OP_NOP			0x0000
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c885e54..4046111 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -123,6 +123,14 @@ struct le_scan_params {
 	int timeout;
 };
 
+struct controller_data {
+	struct list_head list;
+	u8 flags;
+	u8 type;
+	u8 length;
+	u8 data[0];
+};
+
 #define HCI_MAX_SHORT_NAME_LENGTH	10
 
 struct amp_assoc {
@@ -280,6 +288,9 @@ struct hci_dev {
 
 	__s8			adv_tx_power;
 
+	struct list_head	controller_data;
+	__u16			adv_data_len;
+
 	int (*open)(struct hci_dev *hdev);
 	int (*close)(struct hci_dev *hdev);
 	int (*flush)(struct hci_dev *hdev);
@@ -747,6 +758,10 @@ void hci_conn_init_sysfs(struct hci_conn *conn);
 void hci_conn_add_sysfs(struct hci_conn *conn);
 void hci_conn_del_sysfs(struct hci_conn *conn);
 
+int hci_controller_data_add(struct hci_dev *hdev, u8 flags, u8 type, u8 length,
+			    u8 *data);
+int hci_controller_data_clear(struct hci_dev *hdev);
+
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
 
 /* ----- LMP capabilities ----- */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 22980a7..f99e0a8 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -350,6 +350,15 @@ struct mgmt_cp_set_device_id {
 } __packed;
 #define MGMT_SET_DEVICE_ID_SIZE		8
 
+#define MGMT_OP_SET_CONTROLLER_DATA	0x0029
+struct mgmt_cp_set_controller_data {
+	__u8	flags;
+	__u8	type;
+	__u8	length;
+	__u8	data[0];
+} __packed;
+#define MGMT_SET_CONTROLLER_DATA_SIZE	3
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5a3400d..e5ab961 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1405,6 +1405,40 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
 	return 0;
 }
 
+int hci_controller_data_add(struct hci_dev *hdev, u8 flags, u8 type, u8 length,
+			    u8 *data)
+{
+	struct controller_data *c_data;
+
+	c_data = kmalloc(sizeof(*c_data) + length, GFP_KERNEL);
+	if (!c_data)
+		return -ENOMEM;
+
+	c_data->flags = flags;
+	c_data->type = type;
+	c_data->length = length;
+	memcpy(c_data->data, data, length);
+
+	list_add(&c_data->list, &hdev->controller_data);
+	hdev->adv_data_len += sizeof(length) + sizeof(type) + length;
+
+	return 0;
+}
+
+int hci_controller_data_clear(struct hci_dev *hdev)
+{
+	struct controller_data *c_data, *n;
+
+	list_for_each_entry_safe(c_data, n, &hdev->controller_data, list) {
+		list_del(&c_data->list);
+		kfree(c_data);
+	}
+
+	hdev->adv_data_len = 0;
+
+	return 0;
+}
+
 struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 	struct bdaddr_list *b;
@@ -1617,6 +1651,7 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_LIST_HEAD(&hdev->long_term_keys);
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
+	INIT_LIST_HEAD(&hdev->controller_data);
 
 	INIT_WORK(&hdev->rx_work, hci_rx_work);
 	INIT_WORK(&hdev->cmd_work, hci_cmd_work);
@@ -1781,6 +1816,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
 	hci_link_keys_clear(hdev);
 	hci_smp_ltks_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
+	hci_controller_data_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_dev_put(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 399e502..1ada019 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2685,6 +2685,76 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 	return 0;
 }
 
+static void update_adv_data(struct hci_dev *hdev)
+{
+	struct hci_cp_le_set_adv_data cp;
+	struct controller_data *d;
+	u8 len, *ptr;
+
+	if (!hdev_is_powered(hdev))
+		return;
+
+	memset(&cp.data, 0, sizeof(cp.data));
+	ptr = cp.data;
+	len = 0;
+
+	list_for_each_entry(d, &hdev->controller_data, list) {
+		u8 entry_len = sizeof(d->length) + sizeof(d->type) + d->length;
+
+		if (len + entry_len > HCI_MAX_ADV_LENGTH) {
+			BT_DBG("Controller data bigger than adv data slot");
+			return;
+		}
+
+		ptr[0] = sizeof(d->type) + d->length;
+		ptr[1] = d->type;
+		memcpy(&ptr[2], d->data, d->length);
+
+		len += entry_len;
+		ptr += entry_len;
+	}
+
+	cp.data_len = len;
+
+	hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
+}
+
+static int set_controller_data(struct sock *sk, struct hci_dev *hdev,
+			       void *data, u16 len)
+{
+	struct mgmt_cp_set_controller_data *cp = data;
+	u8 room;
+
+	BT_DBG("%s", hdev->name);
+
+	if (cp->type != ADV_SERVICE_DATA && cp->type != ADV_MANUFACTURER_DATA)
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA,
+				  MGMT_STATUS_INVALID_PARAMS);
+
+	hci_dev_lock(hdev);
+
+	room = HCI_MAX_ADV_LENGTH - hdev->adv_data_len;
+	if (sizeof(cp->length) + sizeof(cp->type) + cp->length > room) {
+		hci_dev_unlock(hdev);
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA,
+				  MGMT_STATUS_NO_RESOURCES);
+	}
+
+	BT_DBG("flags:0x%02x length:%i type:0x%02x", cp->flags, cp->length,
+	       cp->type);
+
+	hci_controller_data_add(hdev, cp->flags, cp->type, cp->length,
+				cp->data);
+
+	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+		update_adv_data(hdev);
+
+	hci_dev_unlock(hdev);
+
+	return cmd_complete(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA, 0, NULL,
+			    0);
+}
+
 static const struct mgmt_handler {
 	int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
 		     u16 data_len);
@@ -2732,6 +2802,7 @@ static const struct mgmt_handler {
 	{ block_device,           false, MGMT_BLOCK_DEVICE_SIZE },
 	{ unblock_device,         false, MGMT_UNBLOCK_DEVICE_SIZE },
 	{ set_device_id,          false, MGMT_SET_DEVICE_ID_SIZE },
+	{ set_controller_data,    true,  MGMT_SET_CONTROLLER_DATA_SIZE },
 };
 
 
@@ -2911,6 +2982,9 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
 		update_class(hdev);
 		update_name(hdev, hdev->dev_name);
 		update_eir(hdev);
+
+		if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+			update_adv_data(hdev);
 	} else {
 		u8 status = MGMT_STATUS_NOT_POWERED;
 		mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 3/9] Bluetooth: Add HCI command to set advertising data
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes, Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

The information to be broadcasted must be set using this HCI command.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci.h |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index c539314..75b7e58 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -952,6 +952,14 @@ struct hci_cp_le_set_adv_params {
 	__u8     filter_policy;
 } __packed;
 
+#define HCI_MAX_ADV_LENGTH		31
+
+#define HCI_OP_LE_SET_ADV_DATA		0x2008
+struct hci_cp_le_set_adv_data {
+	__u8     data_len;
+	__u8     data[HCI_MAX_ADV_LENGTH];
+} __packed;
+
 #define HCI_OP_LE_SET_SCAN_PARAM	0x200b
 struct hci_cp_le_set_scan_param {
 	__u8    type;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 2/9] Bluetooth: Set advertising parameters on LE setup
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

To enable broadcasting we need to set up the advertising parameters. As these
parameters are constant (only observer will use until now), they are set on LE
setup.

This patch makes the advertising non-connectable as default. To make connectable
advertising using 'hciconfig leadv' command, you must change these parameters
first.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 net/bluetooth/hci_event.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0b9e646..3df6e67 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -592,11 +592,22 @@ static void bredr_setup(struct hci_dev *hdev)
 
 static void le_setup(struct hci_dev *hdev)
 {
+	struct hci_cp_le_set_adv_params params;
+
 	/* Read LE Buffer Size */
 	hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
 
 	/* Read LE Advertising Channel TX Power */
 	hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
+
+	/* Set ADV params */
+	memset(&params, 0, sizeof(params));
+	params.interval_min = __constant_cpu_to_le16(0x0800);
+	params.interval_max = __constant_cpu_to_le16(0x0800);
+	params.type = ADV_NONCONN_IND;
+	params.own_address_type = ADDR_LE_DEV_PUBLIC;
+	params.channel_map = ADV_USE_ALL_CHANNELS;
+	hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_PARAMS, sizeof(params), &params);
 }
 
 static void hci_setup(struct hci_dev *hdev)
@@ -1310,6 +1321,15 @@ static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
 	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
 }
 
+static void hci_cc_le_set_adv_params(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status = *((__u8 *) skb->data);
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	hci_req_complete(hdev, HCI_OP_LE_SET_ADV_PARAMS, status);
+}
+
 static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -2569,6 +2589,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_write_remote_amp_assoc(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_ADV_PARAMS:
+		hci_cc_le_set_adv_params(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
 		break;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 1/9] Bluetooth: Add HCI command to set advertising parameters
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes, Aloisio Almeida Jr
In-Reply-To: <1351094295-10418-1-git-send-email-aloisio.almeida@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Add command to set advertising parameters before enable it.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci.h |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 348f4bf..c539314 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -938,6 +938,20 @@ struct hci_rp_le_read_adv_tx_power {
 	__s8	tx_power;
 } __packed;
 
+#define ADV_USE_ALL_CHANNELS		0x07
+
+#define HCI_OP_LE_SET_ADV_PARAMS	0x2006
+struct hci_cp_le_set_adv_params {
+	__le16   interval_min;
+	__le16   interval_max;
+	__u8     type;
+	__u8     own_address_type;
+	__u8     direct_address_type;
+	__u8     direct_address[6];
+	__u8     channel_map;
+	__u8     filter_policy;
+} __packed;
+
 #define HCI_OP_LE_SET_SCAN_PARAM	0x200b
 struct hci_cp_le_set_scan_param {
 	__u8    type;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 0/9] Add LE broadcaser and observer functionality
From: Aloisio Almeida Jr @ 2012-10-24 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr

Hi all,

This patch series adds broadcaster and observer funcionality.

Yesterday, Johan Hedberg sent "Improved single-mode and LE peripheral support"
patch series, that has lots of conflicts with this implementation. Such patches
raised some discussions about LE roles interaction and advertising behavior.

The main intention of this submission is to show the implemenation progress of
broadcast and observer features and try to find the best way to merge them with
peripheral role implementation.

Aloisio Almeida Jr (5):
  Bluetooth: Set advertising parameters on LE setup
  Bluetooth: Add set controller data MGMT command
  Bluetooth: Add set broadcaster MGMT command
  Bluetooth: Refactor le scan helpers to enable observer support
  Bluetooth: Add set observer MGMT command

Jefferson Delfes (4):
  Bluetooth: Add HCI command to set advertising parameters
  Bluetooth: Add HCI command to set advertising data
  Bluetooth: Add unset controller data MGMT command
  Bluetooth: Add HCI command to enable/disable advertising

 include/net/bluetooth/hci.h      |   31 ++++
 include/net/bluetooth/hci_core.h |   33 +++-
 include/net/bluetooth/mgmt.h     |   21 +++
 net/bluetooth/hci_core.c         |  134 +++++++++++---
 net/bluetooth/hci_event.c        |   95 +++++++---
 net/bluetooth/mgmt.c             |  371 ++++++++++++++++++++++++++++++++++++--
 6 files changed, 623 insertions(+), 62 deletions(-)

-- 
1.7.10.4


^ permalink raw reply

* Re: [RFC 1/2] Bluetooth: Add driver extension for vendor specific init
From: Marcel Holtmann @ 2012-10-24 15:18 UTC (permalink / raw)
  To: Ho, Albert O
  Cc: linux-bluetooth, Hedberg, Johan, tedd.hj.an@gmail.com, An, Tedd
In-Reply-To: <95EBF2BD638BE24EB7C4104AF2911E3945F4C895@ORSMSX101.amr.corp.intel.com>

Hi Albert,

> > This patch provides an extension of btusb to support device vendor can 
> > implement their own module to execute the vendor specific device 
> > initialization before the stack sends generic BT device 
> > initialization.
> > 
> > Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
> > ---
> >  drivers/bluetooth/btusb.c        |  191 +++++++++++++++++++++++++-------------
> >  drivers/bluetooth/btusb.h        |   53 +++++++++++
> >  include/net/bluetooth/hci_core.h |   10 ++
> >  net/bluetooth/hci_core.c         |   15 ++-
> >  4 files changed, 204 insertions(+), 65 deletions(-)  create mode 
> > 100644 drivers/bluetooth/btusb.h
> > 
> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c 
> > index f637c25..afa1558 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
> > @@ -26,6 +26,7 @@
> >  
> >  #include <net/bluetooth/bluetooth.h>
> >  #include <net/bluetooth/hci_core.h>
> > +#include "btusb.h"
> >  
> >  #define VERSION "0.6"
> >  
> > @@ -39,14 +40,59 @@ static bool reset = 1;
> >  
> >  static struct usb_driver btusb_driver;
> >  
> > -#define BTUSB_IGNORE		0x01
> > -#define BTUSB_DIGIANSWER	0x02
> > -#define BTUSB_CSR		0x04
> > -#define BTUSB_SNIFFER		0x08
> > -#define BTUSB_BCM92035		0x10
> > -#define BTUSB_BROKEN_ISOC	0x20
> > -#define BTUSB_WRONG_SCO_MTU	0x40
> > -#define BTUSB_ATH3012		0x80
> > +/*
> > + * Create btusb_driver_info struct for each driver_info flags used by
> > + * blacklist since vendor's btusb driver will return btusb_driver_info struct.
> > + */
> > +
> > +/*
> > + * if the device is set to this, this menas that the device is 
> > +generic and
> > + * doesn't require any vendor specific handling  */ static const 
> > +struct btusb_driver_info generic = {
> > +	.description	= "BTUSB Generic",
> > +	.flags		= BTUSB_GENERIC,
> > +};
> > +
> > +static const struct btusb_driver_info ignore = {
> > +	.description	= "BTUSB Ignore",
> > +	.flags		= BTUSB_IGNORE,
> > +};
> 
> >> I like the effort, but I think you went a little bit too far here. For these simple ones, we can easily keep our simple blacklist. It keeps the code more readable than this part. But I do appreciate the attempt in unifying this.
> 
> 
> > +
> > +static const struct btusb_driver_info digianswer = {
> > +	.description	= "BTUSB DIGIANSWER",
> > +	.flags		= BTUSB_DIGIANSWER,
> > +};
> > +
> > +static const struct btusb_driver_info csr = {
> > +	.description	= "BTUSB CSR",
> > +	.flags		= BTUSB_CSR,
> > +};
> > +
> > +static const struct btusb_driver_info sniffer = {
> > +	.description	= "BTUSB Sniffer",
> > +	.flags		= BTUSB_SNIFFER,
> > +};
> > +
> > +static const struct btusb_driver_info bcm92035 = {
> > +	.description	= "BTUSB BCM92035",
> > +	.flags		= BTUSB_BCM92035,
> > +};
> > +
> > +static const struct btusb_driver_info broken_isoc = {
> > +	.description	= "BTUSB Broken ISOC",
> > +	.flags		= BTUSB_BROKEN_ISOC,
> > +};
> > +
> > +static const struct btusb_driver_info wrong_sco_mtu = {
> > +	.description	= "BTUSB Wrong SCO MTU",
> > +	.flags		= BTUSB_WRONG_SCO_MTU,
> > +};
> > +
> > +static const struct btusb_driver_info ath3012 = {
> > +	.description	= "BTUSB Ath3012",
> > +	.flags		= BTUSB_ATH3012,
> > +};
> >  
> >  static struct usb_device_id btusb_table[] = {
> >  	/* Generic Bluetooth USB device */
> > @@ -105,90 +151,89 @@ static struct usb_device_id btusb_table[] = {
> >  
> >  	{ }	/* Terminating entry */
> >  };
> > -
> >  MODULE_DEVICE_TABLE(usb, btusb_table);
> >  
> >  static struct usb_device_id blacklist_table[] = {
> >  	/* CSR BlueCore devices */
> > -	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
> > +	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = (unsigned long) &csr },
> 
> >> Keep the blacklist_table as it is. The important table to modify is btusb_table and use a common driver_info that will be shared between drivers.
> 
> >> That would also make it simple to just add BTUSB_IGNORE or a new BTUSB_VENDOR flag to call out the drivers that have a separate driver with a vendor init function, but would match >> the Bluetooth general USB descriptors.
> 
> I looked at usbnet minidriver as you suggested.  If we do a similar scheme such that btusb_probe() invokes the mini_driver's bind()/unbind() then btusb's usage of driver_info will need to change from storing flags (ex: BTUSB_IGNORE) and change to store "static const struct" where it holds a struct containing the mini-driver's bind/unbind functions (just like usbnet minidriver).   Are you good with this change?  I also want to mention that in the patch containing the BT USB mini driver template, it already has its own module_usb_driver() section with its VID/PID listed.

you know what. Just send around what you have right now after the
cleanup and then I can take another look at it.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 2/7] Bluetooth: mgmt: Restrict BR/EDR settings to BR/EDR-only adapters
From: Marcel Holtmann @ 2012-10-24 15:14 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: Johan Hedberg, linux-bluetooth
In-Reply-To: <CAJdJm_PgxH19t6b0XxmKCa=he8n9gsDro0eRPTV10x+RM9tHNA@mail.gmail.com>

Hi Anderson,

> > That is why I like the explanation above, if we set ourselves as
> > peripheral, then we are peripheral and everything else is out of the
> > question. So either LE is enabled and we act as central or we are acting
> > as peripheral.
> >
> > So broadcaster and observer are extra features on top of central. For me
> > that means we have treat them independent. How much you can be
> > broadcaster and observer and central at the same time is then again a
> > different question that we need to answer.
> 
> So do you suggest we keep Broadcaster/Observer as separate settings
> (which actually we prefer, given that we have been working on
> supporting those modes for BR/EDR only adapters, by using EIR for
> broadcasting data allowed on EIR, such as Manufacturer Specific Data,
> and parsing them from Device Found mgmt event when on Observer mode),
> and keep "Set Low Energy" setting just for Central/Peripheral modes?

if we can stay in central role and do broadcaster/observer as an
additional feature, then yes. If they are mutually exclusive, we have to
find something else.

But with all of this, I do not have the final answer until we tried it
and had a couple of review rounds.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] Bluetooth: Add support for Atheros [04ca:3004]
From: Marcel Holtmann @ 2012-10-24 15:10 UTC (permalink / raw)
  To: Dwaine Garden VE3GIF; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1351054633.13513.YahooMailNeo@web125402.mail.ne1.yahoo.com>

Hi Dwaine,

> Add another vendor specific ID for Atheros AR3012 device.
> This chip is wrapped by Lite-On Technology Corp.
> 
> output of usb-devices:T:  Bus=01 Lev=02 Prnt=02 Port=03 Cnt=01 Dev#=  3 Spd=12   MxCh= 0
> D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=04ca ProdID=3004 Rev= 0.02
> S:  Manufacturer=Atheros Communications
> S:  Product=Bluetooth USB Host Controller
> S:  SerialNumber=Alaska Day 2006

I really want to see the endpoints here as well. So do not cut of the
details of this device.

Regards

Marcel



^ permalink raw reply

* [PATCH v7 16/16] hcitool: Retrieve names from cache directory
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 Makefile.tools  |    2 +-
 tools/hcitool.c |   31 ++++++++++++++++++++++++++-----
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index ec79cea..f7c85ef 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -28,7 +28,7 @@ tools_hciconfig_LDADD = lib/libbluetooth-private.la
 
 tools_hcitool_SOURCES = tools/hcitool.c src/oui.h src/oui.c \
 						src/textfile.h src/textfile.c
-tools_hcitool_LDADD = lib/libbluetooth-private.la
+tools_hcitool_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
 
 tools_sdptool_SOURCES = tools/sdptool.c src/sdp-xml.h src/sdp-xml.c
 tools_sdptool_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
diff --git a/tools/hcitool.c b/tools/hcitool.c
index aefbd68..a05e31f 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -40,6 +40,8 @@
 #include <sys/socket.h>
 #include <signal.h>
 
+#include <glib.h>
+
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
 #include <bluetooth/hci_lib.h>
@@ -409,13 +411,32 @@ static char *major_classes[] = {
 
 static char *get_device_name(const bdaddr_t *local, const bdaddr_t *peer)
 {
-	char filename[PATH_MAX + 1], addr[18];
+	char filename[PATH_MAX + 1];
+	char local_addr[18], peer_addr[18];
+	GKeyFile *key_file;
+	char *str = NULL;
+	int len;
+
+	ba2str(local, local_addr);
+	ba2str(peer, peer_addr);
+
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local_addr,
+			peer_addr);
+	filename[PATH_MAX] = '\0';
+	key_file = g_key_file_new();
+
+	if (g_key_file_load_from_file(key_file, filename, 0, NULL)) {
+		str = g_key_file_get_string(key_file, "General", "Name", NULL);
+		if (str) {
+			len = strlen(str);
+			if (len > HCI_MAX_NAME_LENGTH)
+				str[HCI_MAX_NAME_LENGTH] = '\0';
+		}
+	}
 
-	ba2str(local, addr);
-	create_name(filename, PATH_MAX, STORAGEDIR, addr, "names");
+	g_key_file_free(key_file);
 
-	ba2str(peer, addr);
-	return textfile_get(filename, addr);
+	return str;
 }
 
 /* Display local devices */
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 15/16] input: Retrieve device name from cache directory
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 profiles/input/device.c |   26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 9dd8002..41b7a5c 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -37,6 +37,7 @@
 #include <bluetooth/sdp_lib.h>
 #include <bluetooth/uuid.h>
 
+#include <glib.h>
 #include <gdbus.h>
 
 #include "log.h"
@@ -757,7 +758,9 @@ static struct input_device *input_device_new(struct btd_device *device,
 {
 	struct btd_adapter *adapter = device_get_adapter(device);
 	struct input_device *idev;
-	char name[249], src_addr[18], dst_addr[18];
+	char src_addr[18], dst_addr[18];
+	char filename[PATH_MAX + 1];
+	GKeyFile *key_file;
 
 	idev = g_new0(struct input_device, 1);
 	bacpy(&idev->src, adapter_get_address(adapter));
@@ -770,9 +773,24 @@ static struct input_device *input_device_new(struct btd_device *device,
 	ba2str(&idev->src, src_addr);
 	ba2str(&idev->dst, dst_addr);
 
-	if (read_device_name(src_addr, dst_addr, device_get_addr_type(device),
-				name) == 0)
-		idev->name = g_strdup(name);
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", src_addr,
+			dst_addr);
+	filename[PATH_MAX] = '\0';
+	key_file = g_key_file_new();
+
+	if (g_key_file_load_from_file(key_file, filename, 0, NULL)) {
+		int len;
+
+		idev->name = g_key_file_get_string(key_file, "General",
+								"Name", NULL);
+		if (idev->name) {
+			len = strlen(idev->name);
+			if (len > HCI_MAX_NAME_LENGTH)
+				idev->name[HCI_MAX_NAME_LENGTH] = '\0';
+		}
+	}
+
+	g_key_file_free(key_file);
 
 	if (g_dbus_register_interface(btd_get_dbus_connection(),
 					idev->path, INPUT_DEVICE_INTERFACE,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 14/16] dbusoob: Store device name in cache directory
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 plugins/dbusoob.c |   26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c
index 5c5b6ef..82d512c 100644
--- a/plugins/dbusoob.c
+++ b/plugins/dbusoob.c
@@ -31,6 +31,7 @@
 
 #include <errno.h>
 #include <gdbus.h>
+#include <sys/stat.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
@@ -194,6 +195,11 @@ static gboolean parse_data(DBusMessageIter *data, struct oob_data *remote_data)
 static gboolean store_data(struct btd_adapter *adapter, struct oob_data *data)
 {
 	bdaddr_t bdaddr;
+	char filename[PATH_MAX + 1];
+	char s_addr[18];
+	GKeyFile *key_file;
+	char *str;
+	gsize length = 0;
 
 	str2ba(data->addr, &bdaddr);
 
@@ -207,9 +213,23 @@ static gboolean store_data(struct btd_adapter *adapter, struct oob_data *data)
 		write_remote_class(adapter_get_address(adapter), &bdaddr,
 								data->class);
 
-	if (data->name)
-		write_device_name(adapter_get_address(adapter), &bdaddr, 0,
-								data->name);
+	if (data->name) {
+		ba2str(adapter_get_address(adapter), s_addr);
+		snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
+				s_addr, data->addr);
+		filename[PATH_MAX] = '\0';
+		create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+		key_file = g_key_file_new();
+		g_key_file_load_from_file(key_file, filename, 0, NULL);
+		g_key_file_set_string(key_file, "General", "Name", data->name);
+
+		str = g_key_file_to_data(key_file, &length, NULL);
+		g_file_set_contents(filename, str, length, NULL);
+		g_free(str);
+
+		g_key_file_free(key_file);
+	}
 
 	return TRUE;
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 13/16] device: Retrieve name from cache directory
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/device.c |   25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/device.c b/src/device.c
index bc7f8dd..4e0ac58 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1573,6 +1573,8 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 	const bdaddr_t *src;
 	char srcaddr[18], alias[MAX_NAME_LENGTH + 1];
 	uint16_t vendor, product, version;
+	char filename[PATH_MAX + 1];
+	GKeyFile *key_file;
 
 	device = g_try_malloc0(sizeof(struct btd_device));
 	if (device == NULL)
@@ -1600,7 +1602,28 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 	src = adapter_get_address(adapter);
 	ba2str(src, srcaddr);
 
-	read_device_name(srcaddr, address, bdaddr_type, device->name);
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", srcaddr,
+			address);
+	filename[PATH_MAX] = '\0';
+	key_file = g_key_file_new();
+
+	if (g_key_file_load_from_file(key_file, filename, 0, NULL)) {
+		char *str;
+		int len;
+
+		str = g_key_file_get_string(key_file, "General", "Name", NULL);
+		if (str) {
+			len = strlen(str);
+			if (len > HCI_MAX_NAME_LENGTH)
+				str[HCI_MAX_NAME_LENGTH] = '\0';
+
+			strcpy(device->name, str);
+			g_free(str);
+		}
+	}
+
+	g_key_file_free(key_file);
+
 	if (read_device_alias(srcaddr, address, bdaddr_type, alias,
 							sizeof(alias)) == 0)
 		device->alias = g_strdup(alias);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 12/16] event: Remove write of LastSeen info
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/event.c |   13 -------------
 1 file changed, 13 deletions(-)

diff --git a/src/event.c b/src/event.c
index 3c43135..d7daed2 100644
--- a/src/event.c
+++ b/src/event.c
@@ -221,17 +221,6 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
 	device_simple_pairing_complete(device, status);
 }
 
-static void update_lastseen(bdaddr_t *sba, bdaddr_t *dba, uint8_t dba_type)
-{
-	time_t t;
-	struct tm *tm;
-
-	t = time(NULL);
-	tm = gmtime(&t);
-
-	write_lastseen_info(sba, dba, dba_type, tm);
-}
-
 static void update_lastused(bdaddr_t *sba, bdaddr_t *dba, uint8_t dba_type)
 {
 	time_t t;
@@ -256,8 +245,6 @@ void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint8_t bdaddr_type
 		return;
 	}
 
-	update_lastseen(local, peer, bdaddr_type);
-
 	adapter_update_found_devices(adapter, peer, bdaddr_type, rssi,
 					confirm_name, legacy, data, data_len);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 11/16] adapter: Move storage names to cache directory
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/adapter.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/event.c   |   24 ++++++++++++++---
 2 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index ecdc948..8e6cbaa 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2493,6 +2493,58 @@ void btd_adapter_unref(struct btd_adapter *adapter)
 	g_free(path);
 }
 
+static void convert_names_entry(char *key, char *value, void *user_data)
+{
+	char *address = user_data;
+	char filename[PATH_MAX + 1];
+	char *str = key;
+	GKeyFile *key_file;
+	char *data;
+	gsize length = 0;
+
+	if (strchr(key, '#'))
+		str[17] = '\0';
+
+	if (bachk(str) != 0)
+		return;
+
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", address, str);
+	filename[PATH_MAX] = '\0';
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, filename, 0, NULL);
+	g_key_file_set_string(key_file, "General", "Name", value);
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(filename, data, length, NULL);
+	g_free(data);
+
+	g_key_file_free(key_file);
+}
+
+static void convert_device_storage(struct btd_adapter *adapter)
+{
+	char filename[PATH_MAX + 1];
+	char address[18];
+	char *str;
+
+	ba2str(&adapter->bdaddr, address);
+
+	/* Convert device's name cache */
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/names", address);
+	filename[PATH_MAX] = '\0';
+
+	str = textfile_get(filename, "converted");
+	if (str && strcmp(str, "yes") == 0) {
+		DBG("Legacy names file already converted");
+	} else {
+		textfile_foreach(filename, convert_names_entry, address);
+		textfile_put(filename, "converted", "yes");
+	}
+	free(str);
+}
+
 static void convert_config(struct btd_adapter *adapter, const char *filename,
 				GKeyFile *key_file)
 {
@@ -2654,6 +2706,7 @@ gboolean adapter_init(struct btd_adapter *adapter, gboolean up)
 		btd_adapter_gatt_server_start(adapter);
 
 	load_config(adapter);
+	convert_device_storage(adapter);
 	load_drivers(adapter);
 	btd_profile_foreach(probe_profile, adapter);
 	clear_blocked(adapter);
@@ -2935,9 +2988,31 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
 		write_remote_appearance(&adapter->bdaddr, bdaddr, bdaddr_type,
 							eir_data.appearance);
 
-	if (eir_data.name != NULL && eir_data.name_complete)
-		write_device_name(&adapter->bdaddr, bdaddr, bdaddr_type,
-								eir_data.name);
+	if (eir_data.name != NULL && eir_data.name_complete) {
+		char filename[PATH_MAX + 1];
+		char s_addr[18], d_addr[18];
+		GKeyFile *key_file;
+		char *data;
+		gsize length = 0;
+
+		ba2str(&adapter->bdaddr, s_addr);
+		ba2str(bdaddr, d_addr);
+		snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
+				s_addr, d_addr);
+		filename[PATH_MAX] = '\0';
+		create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+		key_file = g_key_file_new();
+		g_key_file_load_from_file(key_file, filename, 0, NULL);
+		g_key_file_set_string(key_file, "General", "Name",
+					eir_data.name);
+
+		data = g_key_file_to_data(key_file, &length, NULL);
+		g_file_set_contents(filename, data, length, NULL);
+		g_free(data);
+
+		g_key_file_free(key_file);
+	}
 
 	/* Avoid creating LE device if it's not discoverable */
 	if (bdaddr_type != BDADDR_BREDR &&
diff --git a/src/event.c b/src/event.c
index 48aeffd..3c43135 100644
--- a/src/event.c
+++ b/src/event.c
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <string.h>
+#include <sys/stat.h>
 
 #include <bluetooth/bluetooth.h>
 
@@ -265,7 +266,11 @@ void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name)
 {
 	struct btd_adapter *adapter;
 	struct btd_device *device;
-	uint8_t peer_type;
+	char filename[PATH_MAX + 1];
+	char local_addr[18], peer_addr[18];
+	GKeyFile *key_file;
+	char *data;
+	gsize length = 0;
 
 	if (!g_utf8_validate(name, -1, NULL)) {
 		int i;
@@ -282,9 +287,22 @@ void btd_event_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name)
 	if (!get_adapter_and_device(local, peer, &adapter, &device, FALSE))
 		return;
 
-	peer_type = device_get_addr_type(device);
+	ba2str(local, local_addr);
+	ba2str(peer, peer_addr);
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local_addr,
+			peer_addr);
+	filename[PATH_MAX] = '\0';
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, filename, 0, NULL);
+	g_key_file_set_string(key_file, "General", "Name", name);
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(filename, data, length, NULL);
+	g_free(data);
 
-	write_device_name(local, peer, peer_type, name);
+	g_key_file_free(key_file);
 
 	if (device)
 		device_set_name(device, name);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 10/16] TODO: Add entry to remove storage convertion function
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 TODO |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/TODO b/TODO
index ca72cd6..bc9bf9c 100644
--- a/TODO
+++ b/TODO
@@ -30,6 +30,12 @@ General
   Priority: Low
   Complexity: C1
 
+- Function in src/adapter.c to convert old storage files to new ini-file format
+  should be removed 6-8 months after first BlueZ 5 release.
+
+  Priority: Low
+  Complexity: C1
+
 BlueZ 5
 =======
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 09/16] adapter: Move saved config to ini-file format
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

Read and write config file in ini-file format.
If the file can not be loaded, try to convert legacy configuration.
---
 src/adapter.c |  206 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 168 insertions(+), 38 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index a2a5da9..ecdc948 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -33,6 +33,7 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <sys/ioctl.h>
+#include <sys/file.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/uuid.h>
@@ -83,6 +84,8 @@
 #define REMOVE_TEMP_TIMEOUT (3 * 60)
 #define PENDING_FOUND_MAX 5
 
+#define SETTINGS_PATH STORAGEDIR "/%s/settings"
+
 static GSList *adapter_drivers = NULL;
 
 enum session_req_type {
@@ -209,6 +212,49 @@ static uint8_t get_mode(const char *mode)
 		return MODE_UNKNOWN;
 }
 
+static void store_adapter_info(struct btd_adapter *adapter)
+{
+	GKeyFile *key_file;
+	char filename[PATH_MAX + 1];
+	char address[18];
+	char *str;
+	gsize length = 0;
+
+	key_file = g_key_file_new();
+
+	g_key_file_set_string(key_file, "General", "Name", adapter->name);
+
+	g_key_file_set_boolean(key_file, "General", "Powered",
+				adapter->mode > MODE_OFF);
+
+	g_key_file_set_boolean(key_file, "General", "Pairable",
+				adapter->pairable);
+
+	if (adapter->pairable_timeout != main_opts.pairto)
+		g_key_file_set_integer(key_file, "General", "PairableTimeout",
+					adapter->pairable_timeout);
+
+	g_key_file_set_boolean(key_file, "General", "Discoverable",
+				adapter->discoverable);
+
+	if (adapter->discov_timeout != main_opts.discovto)
+		g_key_file_set_integer(key_file, "General",
+					"DiscoverableTimeout",
+					adapter->discov_timeout);
+
+	ba2str(&adapter->bdaddr, address);
+	snprintf(filename, PATH_MAX, SETTINGS_PATH, address);
+	filename[PATH_MAX] = '\0';
+
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+	str = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(filename, str, length, NULL);
+	g_free(str);
+
+	g_key_file_free(key_file);
+}
+
 static struct session_req *session_ref(struct session_req *req)
 {
 	req->refcount++;
@@ -278,7 +324,6 @@ static struct session_req *find_session_by_msg(GSList *list, const DBusMessage *
 static int set_mode(struct btd_adapter *adapter, uint8_t new_mode)
 {
 	int err;
-	const char *modestr;
 
 	if (adapter->pending_mode != NULL)
 		return -EALREADY;
@@ -310,10 +355,9 @@ static int set_mode(struct btd_adapter *adapter, uint8_t new_mode)
 		return err;
 
 done:
-	modestr = mode2str(new_mode);
-	write_device_mode(&adapter->bdaddr, modestr);
+	store_adapter_info(adapter);
 
-	DBG("%s", modestr);
+	DBG("%s", mode2str(new_mode));
 
 	return 0;
 }
@@ -448,7 +492,7 @@ void btd_adapter_pairable_changed(struct btd_adapter *adapter,
 {
 	adapter->pairable = pairable;
 
-	write_device_pairable(&adapter->bdaddr, pairable);
+	store_adapter_info(adapter);
 
 	g_dbus_emit_property_changed(btd_get_dbus_connection(), adapter->path,
 					ADAPTER_INTERFACE, "Pairable");
@@ -710,7 +754,7 @@ static void set_discoverable_timeout(struct btd_adapter *adapter,
 
 	adapter->discov_timeout = timeout;
 
-	write_discoverable_timeout(&adapter->bdaddr, timeout);
+	store_adapter_info(adapter);
 
 	g_dbus_emit_property_changed(conn, adapter->path, ADAPTER_INTERFACE,
 						"DiscoverableTimeout");
@@ -730,7 +774,7 @@ static void set_pairable_timeout(struct btd_adapter *adapter,
 
 	adapter->pairable_timeout = timeout;
 
-	write_pairable_timeout(&adapter->bdaddr, timeout);
+	store_adapter_info(adapter);
 
 	g_dbus_emit_property_changed(conn, adapter->path, ADAPTER_INTERFACE,
 							"PairableTimeout");
@@ -801,7 +845,7 @@ int adapter_set_name(struct btd_adapter *adapter, const char *name)
 		adapter->name = g_strdup(maxname);
 	}
 
-	write_local_name(&adapter->bdaddr, maxname);
+	store_adapter_info(adapter);
 
 	return 0;
 }
@@ -2284,13 +2328,11 @@ static void set_mode_complete(struct btd_adapter *adapter)
 {
 	DBusConnection *conn = btd_get_dbus_connection();
 	struct session_req *pending;
-	const char *modestr;
 	int err;
 
-	modestr = mode2str(adapter->mode);
-	write_device_mode(&adapter->bdaddr, modestr);
+	store_adapter_info(adapter);
 
-	DBG("%s", modestr);
+	DBG("%s", mode2str(adapter->mode));
 
 	if (adapter->mode == MODE_OFF) {
 		g_slist_free_full(adapter->mode_sessions, session_free);
@@ -2451,53 +2493,141 @@ void btd_adapter_unref(struct btd_adapter *adapter)
 	g_free(path);
 }
 
-static void load_config(struct btd_adapter *adapter)
+static void convert_config(struct btd_adapter *adapter, const char *filename,
+				GKeyFile *key_file)
 {
-	char name[MAX_NAME_LENGTH + 1];
 	char address[18];
-	char mode[14];
+	char str[MAX_NAME_LENGTH + 1];
+	char config_path[PATH_MAX + 1];
+	char *converted;
+	gboolean flag;
 	int timeout;
+	uint8_t mode;
+	char *data;
+	gsize length = 0;
 
 	ba2str(&adapter->bdaddr, address);
+	snprintf(config_path, PATH_MAX, STORAGEDIR "/%s/config", address);
+	config_path[PATH_MAX] = '\0';
+
+	converted = textfile_get(config_path, "converted");
+	if (converted) {
+		if (strcmp(converted, "yes") == 0) {
+			DBG("Legacy config file already converted");
+			return;
+		}
+
+		g_free(converted);
+	}
+
+	if (read_local_name(&adapter->bdaddr, str) == 0)
+		g_key_file_set_string(key_file, "General", "Name", str);
+
+	if (read_device_pairable(&adapter->bdaddr, &flag) == 0)
+		g_key_file_set_boolean(key_file, "General", "Pairable", flag);
+
+	if (read_pairable_timeout(address, &timeout) == 0)
+		g_key_file_set_integer(key_file, "General",
+						"PairableTimeout", timeout);
+
+	if (read_discoverable_timeout(address, &timeout) == 0)
+		g_key_file_set_integer(key_file, "General",
+						"DiscoverableTimeout", timeout);
+
+	if (read_device_mode(address, str, sizeof(str)) == 0) {
+		mode = get_mode(str);
+		g_key_file_set_boolean(key_file, "General", "Powered",
+					mode > MODE_OFF);
+	}
+
+	if (read_on_mode(address, str, sizeof(str)) == 0) {
+		mode = get_mode(str);
+		g_key_file_set_boolean(key_file, "General", "Discoverable",
+					mode == MODE_DISCOVERABLE);
+	}
+
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(filename, data, length, NULL);
+	g_free(data);
+
+	textfile_put(config_path, "converted", "yes");
+}
+
+static void load_config(struct btd_adapter *adapter)
+{
+	GKeyFile *key_file;
+	char filename[PATH_MAX + 1];
+	char address[18];
+	gboolean powered;
+	GError *gerr = NULL;
+
+	ba2str(&adapter->bdaddr, address);
+
+	key_file = g_key_file_new();
+
+	snprintf(filename, PATH_MAX, SETTINGS_PATH, address);
+	filename[PATH_MAX] = '\0';
+
+	if (!g_key_file_load_from_file(key_file, filename, 0, NULL))
+		convert_config(adapter, filename, key_file);
 
 	/* Get name */
-	if (read_local_name(&adapter->bdaddr, name) < 0)
-		adapter->name = NULL;
-	else
-		adapter->name = g_strdup(name);
+	adapter->name = g_key_file_get_string(key_file, "General",
+								"Name", NULL);
 
 	/* Set class */
 	adapter->dev_class = main_opts.class;
 
 	/* Get pairable mode */
-	if (read_device_pairable(&adapter->bdaddr, &adapter->pairable) < 0)
+	adapter->pairable = g_key_file_get_boolean(key_file, "General",
+							"Pairable", &gerr);
+	if (gerr) {
 		adapter->pairable = TRUE;
+		g_error_free(gerr);
+		gerr = NULL;
+	}
 
 	/* Get pairable timeout */
-	if (read_pairable_timeout(address, &timeout) < 0)
+	adapter->pairable_timeout = g_key_file_get_integer(key_file, "General",
+						"PairableTimeout", &gerr);
+	if (gerr) {
 		adapter->pairable_timeout = main_opts.pairto;
-	else
-		adapter->pairable_timeout = timeout;
+		g_error_free(gerr);
+		gerr = NULL;
+	}
+
+	/* Get discoverable mode */
+	adapter->discoverable = g_key_file_get_boolean(key_file, "General",
+							"Discoverable", &gerr);
+	if (gerr) {
+		adapter->discoverable = (main_opts.mode == MODE_DISCOVERABLE);
+		g_error_free(gerr);
+		gerr = NULL;
+	}
 
 	/* Get discoverable timeout */
-	if (read_discoverable_timeout(address, &timeout) < 0)
+	adapter->discov_timeout = g_key_file_get_integer(key_file, "General",
+						"DiscoverableTimeout", &gerr);
+	if (gerr) {
 		adapter->discov_timeout = main_opts.discovto;
-	else
-		adapter->discov_timeout = timeout;
+		g_error_free(gerr);
+		gerr = NULL;
+	}
 
-	/* Get mode */
-	if (main_opts.remember_powered == FALSE)
-		adapter->mode = main_opts.mode;
-	else if (read_device_mode(address, mode, sizeof(mode)) == 0)
-		adapter->mode = get_mode(mode);
-	else
+	/* Get powered mode */
+	powered = g_key_file_get_boolean(key_file, "General", "Powered",
+						&gerr);
+	if (gerr) {
 		adapter->mode = main_opts.mode;
-
-	/* Get on mode */
-	if (read_on_mode(address, mode, sizeof(mode)) == 0)
-		adapter->discoverable = (strcasecmp("discoverable", mode) == 0);
-	else
-		adapter->discoverable = (adapter->mode == MODE_DISCOVERABLE);
+		g_error_free(gerr);
+		gerr = NULL;
+	} else if (powered) {
+		adapter->mode = adapter->discoverable ? MODE_DISCOVERABLE :
+							MODE_CONNECTABLE;
+	} else
+		adapter->mode = MODE_OFF;
 
 	mgmt_set_connectable(adapter->dev_id, TRUE);
 	mgmt_set_discoverable(adapter->dev_id, adapter->discoverable,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 08/16] adapter: Read mode in storage at init
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

Mgmt interface allows to change connectable and discoverable adapter
status even if the adapter is off. So both status are changed during
adapter init.
Remove on_mode from btd_adapter_get_mode(), as it is no more used.
Update src/mgmt.c and plugins/neard.c
---
 plugins/neard.c |    2 +-
 src/adapter.c   |   75 +++++++++++++++++++++++++++++--------------------------
 src/adapter.h   |    1 -
 src/mgmt.c      |   17 +++----------
 src/mgmt.h      |    1 +
 5 files changed, 45 insertions(+), 51 deletions(-)

diff --git a/plugins/neard.c b/plugins/neard.c
index 2da5024..8018977 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -376,7 +376,7 @@ static int check_adapter(struct btd_adapter *adapter)
 	if (btd_adapter_check_oob_handler(adapter))
 		return -EINPROGRESS;
 
-	btd_adapter_get_mode(adapter, NULL, NULL, NULL, &pairable);
+	btd_adapter_get_mode(adapter, NULL, NULL, &pairable);
 
 	if (!pairable || !adapter_get_agent(adapter))
 		return -ENOENT;
diff --git a/src/adapter.c b/src/adapter.c
index a91e9bb..a2a5da9 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -156,6 +156,7 @@ struct btd_adapter {
 	guint auto_timeout_id;		/* Automatic connections timeout */
 	sdp_list_t *services;		/* Services associated to adapter */
 
+	gboolean discoverable;		/* discoverable state */
 	gboolean pairable;		/* pairable state */
 	gboolean initialized;
 
@@ -196,7 +197,7 @@ static const char *mode2str(uint8_t mode)
 	}
 }
 
-static uint8_t get_mode(const bdaddr_t *bdaddr, const char *mode)
+static uint8_t get_mode(const char *mode)
 {
 	if (strcasecmp("off", mode) == 0)
 		return MODE_OFF;
@@ -204,15 +205,7 @@ static uint8_t get_mode(const bdaddr_t *bdaddr, const char *mode)
 		return MODE_CONNECTABLE;
 	else if (strcasecmp("discoverable", mode) == 0)
 		return MODE_DISCOVERABLE;
-	else if (strcasecmp("on", mode) == 0) {
-		char onmode[14], srcaddr[18];
-
-		ba2str(bdaddr, srcaddr);
-		if (read_on_mode(srcaddr, onmode, sizeof(onmode)) < 0)
-			return MODE_CONNECTABLE;
-
-		return get_mode(bdaddr, onmode);
-	} else
+	else
 		return MODE_UNKNOWN;
 }
 
@@ -373,11 +366,8 @@ static void set_powered(struct btd_adapter *adapter, gboolean powered,
 	uint8_t mode;
 	int err;
 
-	if (powered) {
-		mode = get_mode(&adapter->bdaddr, "on");
-		return set_discoverable(adapter, mode == MODE_DISCOVERABLE,
-									id);
-	}
+	if (powered)
+		return set_discoverable(adapter, adapter->discoverable, id);
 
 	mode = MODE_OFF;
 
@@ -1406,7 +1396,10 @@ static DBusMessage *request_session(DBusConnection *conn,
 	if (!adapter->mode_sessions)
 		adapter->global_mode = adapter->mode;
 
-	new_mode = get_mode(&adapter->bdaddr, "on");
+	if (adapter->discoverable)
+		new_mode = MODE_DISCOVERABLE;
+	else
+		new_mode = MODE_CONNECTABLE;
 
 	req = find_session(adapter->mode_sessions, sender);
 	if (req) {
@@ -2120,25 +2113,15 @@ static void call_adapter_powered_callbacks(struct btd_adapter *adapter,
 }
 
 void btd_adapter_get_mode(struct btd_adapter *adapter, uint8_t *mode,
-						uint8_t *on_mode,
 						uint16_t *discoverable_timeout,
 						gboolean *pairable)
 {
-	char str[14], address[18];
+	char address[18];
 
 	ba2str(&adapter->bdaddr, address);
 
-	if (mode) {
-		if (main_opts.remember_powered == FALSE)
-			*mode = main_opts.mode;
-		else if (read_device_mode(address, str, sizeof(str)) == 0)
-			*mode = get_mode(&adapter->bdaddr, str);
-		else
-			*mode = main_opts.mode;
-	}
-
-	if (on_mode)
-		*on_mode = get_mode(&adapter->bdaddr, "on");
+	if (mode)
+		*mode = adapter->mode;
 
 	if (discoverable_timeout)
 		*discoverable_timeout = adapter->discov_timeout;
@@ -2224,10 +2207,13 @@ void btd_adapter_start(struct btd_adapter *adapter)
 	adapter->up = TRUE;
 	adapter->off_timer = 0;
 
-	if (adapter->scan_mode & SCAN_INQUIRY)
+	if (adapter->scan_mode & SCAN_INQUIRY) {
 		adapter->mode = MODE_DISCOVERABLE;
-	else
+		adapter->discoverable = TRUE;
+	} else {
 		adapter->mode = MODE_CONNECTABLE;
+		adapter->discoverable = FALSE;
+	}
 
 	g_dbus_emit_property_changed(btd_get_dbus_connection(), adapter->path,
 						ADAPTER_INTERFACE, "Powered");
@@ -2469,6 +2455,7 @@ static void load_config(struct btd_adapter *adapter)
 {
 	char name[MAX_NAME_LENGTH + 1];
 	char address[18];
+	char mode[14];
 	int timeout;
 
 	ba2str(&adapter->bdaddr, address);
@@ -2497,6 +2484,24 @@ static void load_config(struct btd_adapter *adapter)
 		adapter->discov_timeout = main_opts.discovto;
 	else
 		adapter->discov_timeout = timeout;
+
+	/* Get mode */
+	if (main_opts.remember_powered == FALSE)
+		adapter->mode = main_opts.mode;
+	else if (read_device_mode(address, mode, sizeof(mode)) == 0)
+		adapter->mode = get_mode(mode);
+	else
+		adapter->mode = main_opts.mode;
+
+	/* Get on mode */
+	if (read_on_mode(address, mode, sizeof(mode)) == 0)
+		adapter->discoverable = (strcasecmp("discoverable", mode) == 0);
+	else
+		adapter->discoverable = (adapter->mode == MODE_DISCOVERABLE);
+
+	mgmt_set_connectable(adapter->dev_id, TRUE);
+	mgmt_set_discoverable(adapter->dev_id, adapter->discoverable,
+				adapter->discov_timeout);
 }
 
 gboolean adapter_init(struct btd_adapter *adapter, gboolean up)
@@ -2877,9 +2882,11 @@ void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode)
 		break;
 	case SCAN_PAGE:
 		adapter->mode = MODE_CONNECTABLE;
+		adapter->discoverable = FALSE;
 		break;
 	case (SCAN_PAGE | SCAN_INQUIRY):
 		adapter->mode = MODE_DISCOVERABLE;
+		adapter->discoverable = TRUE;
 		break;
 	default:
 		/* ignore, reserved */
@@ -3182,17 +3189,13 @@ gboolean adapter_powering_down(struct btd_adapter *adapter)
 
 int btd_adapter_restore_powered(struct btd_adapter *adapter)
 {
-	char mode[14], address[18];
-
 	if (!main_opts.remember_powered)
 		return -EINVAL;
 
 	if (adapter->up)
 		return 0;
 
-	ba2str(&adapter->bdaddr, address);
-	if (read_device_mode(address, mode, sizeof(mode)) == 0 &&
-						g_str_equal(mode, "off"))
+	if (adapter->mode == MODE_OFF)
 		return 0;
 
 	return mgmt_set_powered(adapter->dev_id, TRUE);
diff --git a/src/adapter.h b/src/adapter.h
index be69781..54f9ea7 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -81,7 +81,6 @@ void btd_adapter_start(struct btd_adapter *adapter);
 int btd_adapter_stop(struct btd_adapter *adapter);
 
 void btd_adapter_get_mode(struct btd_adapter *adapter, uint8_t *mode,
-						uint8_t *on_mode,
 						uint16_t *discoverable_timeout,
 						gboolean *pairable);
 
diff --git a/src/mgmt.c b/src/mgmt.c
index f179dfa..8fe5100 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -207,7 +207,7 @@ static int mgmt_set_mode(int index, uint16_t opcode, uint8_t val)
 	return 0;
 }
 
-static int mgmt_set_connectable(int index, gboolean connectable)
+int mgmt_set_connectable(int index, gboolean connectable)
 {
 	DBG("index %d connectable %d", index, connectable);
 	return mgmt_set_mode(index, MGMT_OP_SET_CONNECTABLE, connectable);
@@ -315,27 +315,18 @@ static void update_settings(struct btd_adapter *adapter, uint32_t settings)
 {
 	struct controller_info *info;
 	gboolean pairable;
-	uint8_t on_mode;
 	uint16_t index, discoverable_timeout;
 
 	DBG("new settings %x", settings);
 
-	btd_adapter_get_mode(adapter, NULL, &on_mode, &discoverable_timeout,
-								&pairable);
+	btd_adapter_get_mode(adapter, NULL, &discoverable_timeout, &pairable);
 
 	index = adapter_get_dev_id(adapter);
 
 	info = &controllers[index];
 
-	if (on_mode == MODE_DISCOVERABLE && !mgmt_discoverable(settings)) {
-		if(!mgmt_connectable(settings))
-			mgmt_set_connectable(index, TRUE);
-		mgmt_set_discoverable(index, TRUE, discoverable_timeout);
-	} else if (on_mode == MODE_CONNECTABLE && !mgmt_connectable(settings)) {
-		mgmt_set_connectable(index, TRUE);
-	} else if (mgmt_powered(settings)) {
+	if (mgmt_powered(settings))
 		adapter_mode_changed(adapter, create_mode(settings));
-	}
 
 	if (mgmt_pairable(settings) != pairable)
 		mgmt_set_pairable(index, pairable);
@@ -1108,7 +1099,7 @@ static void read_info_complete(int sk, uint16_t index, void *buf, size_t len)
 	btd_adapter_get_major_minor(adapter, &major, &minor);
 	mgmt_set_dev_class(index, major, minor);
 
-	btd_adapter_get_mode(adapter, &mode, NULL, NULL, NULL);
+	btd_adapter_get_mode(adapter, &mode, NULL, NULL);
 	if (mode == MODE_OFF && mgmt_powered(info->current_settings)) {
 		mgmt_set_powered(index, FALSE);
 		return;
diff --git a/src/mgmt.h b/src/mgmt.h
index a2c0497..daa168a 100644
--- a/src/mgmt.h
+++ b/src/mgmt.h
@@ -26,6 +26,7 @@ int mgmt_setup(void);
 void mgmt_cleanup(void);
 
 int mgmt_set_powered(int index, gboolean powered);
+int mgmt_set_connectable(int index, gboolean connectable);
 int mgmt_set_discoverable(int index, gboolean discoverable, uint16_t timeout);
 int mgmt_set_pairable(int index, gboolean pairable);
 int mgmt_set_name(int index, const char *name);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 07/16] adapter: Read discoverable timeout in storage at init
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/adapter.c |   19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 918991c..a91e9bb 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2097,16 +2097,6 @@ static void load_connections(struct btd_adapter *adapter)
 	g_slist_free_full(conns, g_free);
 }
 
-static int get_discoverable_timeout(const char *src)
-{
-	int timeout;
-
-	if (read_discoverable_timeout(src, &timeout) == 0)
-		return timeout;
-
-	return main_opts.discovto;
-}
-
 static void set_auto_connect(gpointer data, gpointer user_data)
 {
 	struct btd_device *device = data;
@@ -2151,7 +2141,7 @@ void btd_adapter_get_mode(struct btd_adapter *adapter, uint8_t *mode,
 		*on_mode = get_mode(&adapter->bdaddr, "on");
 
 	if (discoverable_timeout)
-		*discoverable_timeout = get_discoverable_timeout(address);
+		*discoverable_timeout = adapter->discov_timeout;
 
 	if (pairable)
 		*pairable = adapter->pairable;
@@ -2232,7 +2222,6 @@ void btd_adapter_start(struct btd_adapter *adapter)
 
 	adapter->off_requested = FALSE;
 	adapter->up = TRUE;
-	adapter->discov_timeout = get_discoverable_timeout(address);
 	adapter->off_timer = 0;
 
 	if (adapter->scan_mode & SCAN_INQUIRY)
@@ -2502,6 +2491,12 @@ static void load_config(struct btd_adapter *adapter)
 		adapter->pairable_timeout = main_opts.pairto;
 	else
 		adapter->pairable_timeout = timeout;
+
+	/* Get discoverable timeout */
+	if (read_discoverable_timeout(address, &timeout) < 0)
+		adapter->discov_timeout = main_opts.discovto;
+	else
+		adapter->discov_timeout = timeout;
 }
 
 gboolean adapter_init(struct btd_adapter *adapter, gboolean up)
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 06/16] adapter: Read pairable timeout in storage at init
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/adapter.c |   21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index d0a8404..918991c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2107,16 +2107,6 @@ static int get_discoverable_timeout(const char *src)
 	return main_opts.discovto;
 }
 
-static int get_pairable_timeout(const char *src)
-{
-	int timeout;
-
-	if (read_pairable_timeout(src, &timeout) == 0)
-		return timeout;
-
-	return main_opts.pairto;
-}
-
 static void set_auto_connect(gpointer data, gpointer user_data)
 {
 	struct btd_device *device = data;
@@ -2243,7 +2233,6 @@ void btd_adapter_start(struct btd_adapter *adapter)
 	adapter->off_requested = FALSE;
 	adapter->up = TRUE;
 	adapter->discov_timeout = get_discoverable_timeout(address);
-	adapter->pairable_timeout = get_pairable_timeout(address);
 	adapter->off_timer = 0;
 
 	if (adapter->scan_mode & SCAN_INQUIRY)
@@ -2490,6 +2479,10 @@ void btd_adapter_unref(struct btd_adapter *adapter)
 static void load_config(struct btd_adapter *adapter)
 {
 	char name[MAX_NAME_LENGTH + 1];
+	char address[18];
+	int timeout;
+
+	ba2str(&adapter->bdaddr, address);
 
 	/* Get name */
 	if (read_local_name(&adapter->bdaddr, name) < 0)
@@ -2503,6 +2496,12 @@ static void load_config(struct btd_adapter *adapter)
 	/* Get pairable mode */
 	if (read_device_pairable(&adapter->bdaddr, &adapter->pairable) < 0)
 		adapter->pairable = TRUE;
+
+	/* Get pairable timeout */
+	if (read_pairable_timeout(address, &timeout) < 0)
+		adapter->pairable_timeout = main_opts.pairto;
+	else
+		adapter->pairable_timeout = timeout;
 }
 
 gboolean adapter_init(struct btd_adapter *adapter, gboolean up)
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v7 05/16] adapter: Move pairable read to load_config()
From: Frédéric Danis @ 2012-10-24 14:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351089258-25179-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/adapter.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 310d1cf..d0a8404 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2499,6 +2499,10 @@ static void load_config(struct btd_adapter *adapter)
 
 	/* Set class */
 	adapter->dev_class = main_opts.class;
+
+	/* Get pairable mode */
+	if (read_device_pairable(&adapter->bdaddr, &adapter->pairable) < 0)
+		adapter->pairable = TRUE;
 }
 
 gboolean adapter_init(struct btd_adapter *adapter, gboolean up)
@@ -2526,10 +2530,6 @@ gboolean adapter_init(struct btd_adapter *adapter, gboolean up)
 	clear_blocked(adapter);
 	load_devices(adapter);
 
-	/* Set pairable mode */
-	if (read_device_pairable(&adapter->bdaddr, &adapter->pairable) < 0)
-		adapter->pairable = TRUE;
-
 	/* retrieve the active connections: address the scenario where
 	 * the are active connections before the daemon've started */
 	load_connections(adapter);
-- 
1.7.9.5


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox