Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH 3/5] adapter: Convert ccc file
From: Anderson Lizardo @ 2012-12-14 17:31 UTC (permalink / raw)
  To: Frédéric Danis; +Cc: linux-bluetooth
In-Reply-To: <1355503519-26573-3-git-send-email-frederic.danis@linux.intel.com>

Hi Frédéric,

On Fri, Dec 14, 2012 at 12:45 PM, Frédéric Danis
<frederic.danis@linux.intel.com> wrote:
> ---
>  doc/settings-storage.txt |   14 +++++++++++
>  src/adapter.c            |   63 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 77 insertions(+)
>
> diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
> index 11b127f..ced51d9 100644
> --- a/doc/settings-storage.txt
> +++ b/doc/settings-storage.txt
> @@ -31,6 +31,7 @@ contains:
>     contains:
>      - an info file
>      - an attributes file containing attributes of remote LE services
> +    - a ccc file containing CCC info of remote LE services

Just a few textual improvements:

"- a ccc file containing persistent Client Characteristic
Configuration (CCC) descriptor information for GATT characteristics"

> +CCC file format
> +======================
> +
> +The ccc file stores CCC  informations related to remote device.
> +
> +Informations are stored using their handle as group name (decimal format).

"""
The ccc file stores the current CCC descriptor values for GATT
characteristics which have notification/indication enabled by the
remote device.

Information is stored using CCC attribute handle as group name (in
decimal format).
"""

> +
> +Each group contains:
> +
> +  Value                        String          Value of the CCC as hexadecimal encoded

"CCC descriptor value encoded in hexadecimal"

> +                                       string
> +

Everything else looks good as per my review.

Best Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* [PATCH 00/12] Add LE broadcaster and observer functionality
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes

This patch series adds broadcaster and observer functionality.

For the userspace, we are updating our branch and we will send it in s few
days.

Aloisio Almeida Jr (10):
  Bluetooth: Set advertising parameters on LE setup
  Bluetooth: Add set controller data MGMT command
  Bluetooth: Add set broadcaster MGMT command
  Bluetooth: Advertise controller data in broadcaster mode
  Bluetooth: Stop to acquire hdev lock inside hci_update_ad
  Bluetooth: Enable on-the-fly update of broadcast data
  Bluetooth: Enable support for broadcaster mode when powered off.
  Bluetooth: Refactor le scan helpers to enable observer support
  Bluetooth: Add set observer MGMT command
  Bluetooth: Enable support for observer mode when powered off.

Jefferson Delfes (2):
  Bluetooth: Add HCI command to set advertising parameters
  Bluetooth: Add unset controller data MGMT command

 include/net/bluetooth/hci.h      |  19 +++
 include/net/bluetooth/hci_core.h |  42 ++++-
 include/net/bluetooth/mgmt.h     |  21 +++
 net/bluetooth/hci_core.c         | 183 ++++++++++++++++-----
 net/bluetooth/hci_event.c        | 121 +++++++++-----
 net/bluetooth/mgmt.c             | 335 +++++++++++++++++++++++++++++++++++++--
 6 files changed, 628 insertions(+), 93 deletions(-)

-- 
1.8.0.2


^ permalink raw reply

* [PATCH 01/12] Bluetooth: Add HCI command to set advertising parameters
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes, Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

Add command to set advertising parameters before enable it.

Signed-off-by: Jefferson Delfes <jefferson.delfes@openbossa.org>
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 45eee08..e89311d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -959,6 +959,20 @@ struct hci_cp_le_set_adv_data {
 
 #define HCI_OP_LE_SET_ADV_ENABLE	0x200a
 
+#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.8.0.2


^ permalink raw reply related

* [PATCH 02/12] Bluetooth: Set advertising parameters on LE setup
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>

To enable broadcasting we need to set up the advertising parameters. As these
parameters are constant (only broadcaster is using 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 705078a..8f84f71 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -606,11 +606,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)
@@ -1359,6 +1370,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);
@@ -2680,6 +2700,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.8.0.2


^ permalink raw reply related

* [PATCH 03/12] Bluetooth: Add set controller data MGMT command
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr, Jefferson Delfes
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>

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

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
Signed-off-by: Jefferson Delfes <jefferson.delfes@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             | 39 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 102 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index e89311d..a89ff01 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -337,6 +337,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 */
 
 /* Low Energy Advertising Flags */
 #define LE_AD_LIMITED		0x01 /* Limited Discoverable */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 014a2ea..49a9ead 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 broadcast_data {
+	struct list_head list;
+	u8 flags;
+	u8 type;
+	u8 length;
+	u8 data[0];
+};
+
 #define HCI_MAX_SHORT_NAME_LENGTH	10
 
 struct amp_assoc {
@@ -282,6 +290,9 @@ struct hci_dev {
 	__u8			adv_data[HCI_MAX_AD_LENGTH];
 	__u8			adv_data_len;
 
+	struct list_head	broadcast_data;
+	__u16			broadcast_data_len;
+
 	int (*open)(struct hci_dev *hdev);
 	int (*close)(struct hci_dev *hdev);
 	int (*flush)(struct hci_dev *hdev);
@@ -752,6 +763,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_broadcast_data_add(struct hci_dev *hdev, u8 flags, u8 type, u8 length,
+			   u8 *data);
+int hci_broadcast_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 ec7d3a7..6d6ee0c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1504,6 +1504,40 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
 	return 0;
 }
 
+int hci_broadcast_data_add(struct hci_dev *hdev, u8 flags, u8 type, u8 length,
+			    u8 *data)
+{
+	struct broadcast_data *b_data;
+
+	b_data = kmalloc(sizeof(*b_data) + length, GFP_KERNEL);
+	if (!b_data)
+		return -ENOMEM;
+
+	b_data->flags = flags;
+	b_data->type = type;
+	b_data->length = length;
+	memcpy(b_data->data, data, length);
+
+	list_add(&b_data->list, &hdev->broadcast_data);
+	hdev->broadcast_data_len += sizeof(length) + sizeof(type) + length;
+
+	return 0;
+}
+
+int hci_broadcast_data_clear(struct hci_dev *hdev)
+{
+	struct broadcast_data *b_data, *n;
+
+	list_for_each_entry_safe(b_data, n, &hdev->broadcast_data, list) {
+		list_del(&b_data->list);
+		kfree(b_data);
+	}
+
+	hdev->broadcast_data_len = 0;
+
+	return 0;
+}
+
 struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 	struct bdaddr_list *b;
@@ -1721,6 +1755,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->broadcast_data);
 
 	INIT_WORK(&hdev->rx_work, hci_rx_work);
 	INIT_WORK(&hdev->cmd_work, hci_cmd_work);
@@ -1887,6 +1922,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_broadcast_data_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_dev_put(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 5d0ef75..4623cf0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2701,6 +2701,44 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 	return 0;
 }
 
+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);
+
+	if (!hdev_is_powered(hdev)) {
+		hci_dev_unlock(hdev);
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA,
+				  MGMT_STATUS_NOT_POWERED);
+	}
+
+	room = HCI_MAX_AD_LENGTH - hdev->broadcast_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_broadcast_data_add(hdev, cp->flags, cp->type, cp->length, cp->data);
+
+	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);
@@ -2748,6 +2786,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 },
 };
 
 
-- 
1.8.0.2


^ permalink raw reply related

* [PATCH 04/12] Bluetooth: Add unset controller data MGMT command
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes, Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

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

Signed-off-by: Jefferson Delfes <jefferson.delfes@openbossa.org>
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             | 24 ++++++++++++++++++++++++
 4 files changed, 50 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 49a9ead..cf8d125 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -765,6 +765,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 
 int hci_broadcast_data_add(struct hci_dev *hdev, u8 flags, u8 type, u8 length,
 			   u8 *data);
+int hci_broadcast_data_remove(struct hci_dev *hdev, u8 type);
 int hci_broadcast_data_clear(struct hci_dev *hdev);
 
 #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 6d6ee0c..d015e1f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1524,6 +1524,25 @@ int hci_broadcast_data_add(struct hci_dev *hdev, u8 flags, u8 type, u8 length,
 	return 0;
 }
 
+int hci_broadcast_data_remove(struct hci_dev *hdev, u8 type)
+{
+	struct broadcast_data *match, *n;
+	int matches = 0;
+
+	list_for_each_entry_safe(match, n, &hdev->broadcast_data, list) {
+		if (type != match->type)
+			continue;
+
+		list_del(&match->list);
+		hdev->broadcast_data_len -= sizeof(match->length) +
+					    sizeof(match->type) + match->length;
+		kfree(match);
+		matches++;
+	}
+
+	return matches;
+}
+
 int hci_broadcast_data_clear(struct hci_dev *hdev)
 {
 	struct broadcast_data *b_data, *n;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4623cf0..0aa96bb 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2739,6 +2739,29 @@ 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;
+
+	BT_DBG("%s type:0x%02x", hdev->name, cp->type);
+
+	hci_dev_lock(hdev);
+
+	if (!hdev_is_powered(hdev)) {
+		hci_dev_unlock(hdev);
+		return cmd_status(sk, hdev->id, MGMT_OP_UNSET_CONTROLLER_DATA,
+				  MGMT_STATUS_NOT_POWERED);
+	}
+
+	hci_broadcast_data_remove(hdev, cp->type);
+
+	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);
@@ -2787,6 +2810,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.8.0.2


^ permalink raw reply related

* [PATCH 05/12] Bluetooth: Add set broadcaster MGMT command
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <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.

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index a89ff01..efbdd3d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -121,6 +121,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 cf8d125..56af0fd 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -131,6 +131,10 @@ struct broadcast_data {
 	u8 data[0];
 };
 
+enum {
+	LE_ADV_REQ_REASON_BROADCASTER,
+};
+
 #define HCI_MAX_SHORT_NAME_LENGTH	10
 
 struct amp_assoc {
@@ -293,6 +297,8 @@ struct hci_dev {
 	struct list_head	broadcast_data;
 	__u16			broadcast_data_len;
 
+	__u8			le_adv_req_reason;
+
 	int (*open)(struct hci_dev *hdev);
 	int (*close)(struct hci_dev *hdev);
 	int (*flush)(struct hci_dev *hdev);
@@ -1122,6 +1128,8 @@ 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, bool changed,
+				  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 8f84f71..46f76d6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1204,6 +1204,7 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
 static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 *sent, status = *((__u8 *) skb->data);
+	__u8 enable;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
 
@@ -1211,13 +1212,30 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 	if (!sent)
 		return;
 
+	enable = *sent;
+
 	hci_dev_lock(hdev);
 
-	if (!status) {
-		if (*sent)
-			set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
-		else
-			clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+	if (hdev->le_adv_req_reason == LE_ADV_REQ_REASON_BROADCASTER) {
+		bool changed = false;
+		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;
+		}
+		if (!test_bit(HCI_INIT, &hdev->flags))
+			mgmt_set_broadcaster_complete(hdev, changed, status);
+	} else {
+		if (!status) {
+			if (enable)
+				set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+			else
+				clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+		}
 	}
 
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0aa96bb..608e81af 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -392,8 +392,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
 	if (enable_hs)
 		settings |= MGMT_SETTING_HS;
 
-	if (lmp_le_capable(hdev))
+	if (lmp_le_capable(hdev)) {
 		settings |= MGMT_SETTING_LE;
+		settings |= MGMT_SETTING_BROADCASTER;
+	}
 
 	return settings;
 }
@@ -420,6 +422,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;
 
@@ -2762,6 +2767,64 @@ 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)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_BROADCASTER,
+				  MGMT_STATUS_NOT_POWERED);
+		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;
+	}
+
+	hdev->le_adv_req_reason = LE_ADV_REQ_REASON_BROADCASTER;
+
+	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);
@@ -2811,6 +2874,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 },
 };
 
 
@@ -3667,6 +3731,33 @@ int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
 	return err;
 }
 
+int mgmt_set_broadcaster_complete(struct hci_dev *hdev, bool changed, u8 status)
+{
+	struct pending_cmd *cmd;
+	struct cmd_lookup match = { NULL, hdev };
+	int err = 0;
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_BROADCASTER, hdev);
+	if (!cmd)
+		return -ENOENT;
+
+	if (status) {
+		u8 mgmt_err = mgmt_status(status);
+		cmd_status_rsp(cmd, &mgmt_err);
+		return err;
+	}
+
+	settings_rsp(cmd, &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.8.0.2


^ permalink raw reply related

* [PATCH 06/12] Bluetooth: Advertise controller data in broadcaster mode
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>

In broadcaster mode, the adapter must advertise the data set by user in
set_controller_data.

According to the spec, the flags field must be ommited if its value is zero.

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

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d015e1f..5ba9fad 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -654,6 +654,30 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
 	return ad_len;
 }
 
+static u8 create_ad_broadcast(struct hci_dev *hdev, u8 *ptr)
+{
+	u16 len = 0;
+	struct broadcast_data *d;
+
+	list_for_each_entry(d, &hdev->broadcast_data, list) {
+		u8 entry_len = sizeof(d->length) + sizeof(d->type) + d->length;
+
+		if (len + entry_len > HCI_MAX_AD_LENGTH) {
+			BT_DBG("Controller data bigger than adv data slot");
+			return len;
+		}
+
+		ptr[0] = sizeof(d->type) + d->length;
+		ptr[1] = d->type;
+		memcpy(&ptr[2], d->data, d->length);
+
+		len += entry_len;
+		ptr += entry_len;
+	}
+
+	return len;
+}
+
 int hci_update_ad(struct hci_dev *hdev)
 {
 	struct hci_cp_le_set_adv_data cp;
@@ -669,7 +693,10 @@ int hci_update_ad(struct hci_dev *hdev)
 
 	memset(&cp, 0, sizeof(cp));
 
-	len = create_ad(hdev, cp.data);
+	if (test_bit(HCI_BROADCASTER, &hdev->dev_flags))
+		len = create_ad_broadcast(hdev, cp.data);
+	else
+		len = create_ad(hdev, cp.data);
 
 	if (hdev->adv_data_len == len &&
 	    memcmp(cp.data, hdev->adv_data, len) == 0) {
-- 
1.8.0.2


^ permalink raw reply related

* [PATCH 07/12] Bluetooth: Stop to acquire hdev lock inside hci_update_ad
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>

In order to enable broadcaster mode even in power off state, hci_update_ad
must be called in mgmt_powered function, that already has the lock.

Removing the locking logic from inside this function is not a big deal as
most of the functions that already call hci_update_ad also have the lock.

The function was renamed to __hci_update_ad to follow the convention.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  2 +-
 net/bluetooth/hci_core.c         | 23 ++++++++---------------
 net/bluetooth/hci_event.c        | 19 +++++++++++--------
 3 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 56af0fd..d5fd56a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -754,7 +754,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
 								u8 *randomizer);
 int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
-int hci_update_ad(struct hci_dev *hdev);
+int __hci_update_ad(struct hci_dev *hdev);
 
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5ba9fad..c692b14 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -678,18 +678,14 @@ static u8 create_ad_broadcast(struct hci_dev *hdev, u8 *ptr)
 	return len;
 }
 
-int hci_update_ad(struct hci_dev *hdev)
+int __hci_update_ad(struct hci_dev *hdev)
 {
 	struct hci_cp_le_set_adv_data cp;
 	u8 len;
 	int err;
 
-	hci_dev_lock(hdev);
-
-	if (!lmp_le_capable(hdev)) {
-		err = -EINVAL;
-		goto unlock;
-	}
+	if (!lmp_le_capable(hdev))
+		return -EINVAL;
 
 	memset(&cp, 0, sizeof(cp));
 
@@ -699,10 +695,8 @@ int hci_update_ad(struct hci_dev *hdev)
 		len = create_ad(hdev, cp.data);
 
 	if (hdev->adv_data_len == len &&
-	    memcmp(cp.data, hdev->adv_data, len) == 0) {
-		err = 0;
-		goto unlock;
-	}
+	    memcmp(cp.data, hdev->adv_data, len) == 0)
+		return 0;
 
 	memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
 	hdev->adv_data_len = len;
@@ -710,9 +704,6 @@ int hci_update_ad(struct hci_dev *hdev)
 	cp.length = len;
 	err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
 
-unlock:
-	hci_dev_unlock(hdev);
-
 	return err;
 }
 
@@ -773,7 +764,9 @@ int hci_dev_open(__u16 dev)
 		hci_dev_hold(hdev);
 		set_bit(HCI_UP, &hdev->flags);
 		hci_notify(hdev, HCI_DEV_UP);
-		hci_update_ad(hdev);
+		hci_dev_lock(hdev);
+		__hci_update_ad(hdev);
+		hci_dev_unlock(hdev);
 		if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
 		    mgmt_valid_hdev(hdev)) {
 			hci_dev_lock(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 46f76d6..b5eb89a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -227,10 +227,10 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 	else if (!status)
 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
 
-	hci_dev_unlock(hdev);
-
 	if (!status && !test_bit(HCI_INIT, &hdev->flags))
-		hci_update_ad(hdev);
+		__hci_update_ad(hdev);
+
+	hci_dev_unlock(hdev);
 
 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
 }
@@ -1110,8 +1110,11 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
 
 	if (!rp->status) {
 		hdev->adv_tx_power = rp->tx_power;
-		if (!test_bit(HCI_INIT, &hdev->flags))
-			hci_update_ad(hdev);
+		if (!test_bit(HCI_INIT, &hdev->flags)) {
+			hci_dev_lock(hdev);
+			__hci_update_ad(hdev);
+			hci_dev_unlock(hdev);
+		}
 	}
 
 	hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
@@ -1238,10 +1241,10 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 		}
 	}
 
-	hci_dev_unlock(hdev);
-
 	if (!test_bit(HCI_INIT, &hdev->flags))
-		hci_update_ad(hdev);
+		__hci_update_ad(hdev);
+
+	hci_dev_unlock(hdev);
 
 	hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
 }
-- 
1.8.0.2


^ permalink raw reply related

* [PATCH 08/12] Bluetooth: Enable on-the-fly update of broadcast data
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>

The broadcast data can be updated with no need to re-enable broadcaster
mode.

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

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 608e81af..e910b11 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2738,6 +2738,9 @@ static int set_controller_data(struct sock *sk, struct hci_dev *hdev,
 
 	hci_broadcast_data_add(hdev, cp->flags, cp->type, cp->length, cp->data);
 
+	if (test_bit(HCI_BROADCASTER, &hdev->dev_flags))
+		__hci_update_ad(hdev);
+
 	hci_dev_unlock(hdev);
 
 	return cmd_complete(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA, 0, NULL,
@@ -2748,6 +2751,7 @@ 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);
 
@@ -2759,7 +2763,10 @@ static int unset_controller_data(struct sock *sk, struct hci_dev *hdev,
 				  MGMT_STATUS_NOT_POWERED);
 	}
 
-	hci_broadcast_data_remove(hdev, cp->type);
+	removed = hci_broadcast_data_remove(hdev, cp->type);
+
+	if (removed && test_bit(HCI_BROADCASTER, &hdev->dev_flags))
+		__hci_update_ad(hdev);
 
 	hci_dev_unlock(hdev);
 
-- 
1.8.0.2


^ permalink raw reply related

* [PATCH 09/12] Bluetooth: Enable support for broadcaster mode when powered off.
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>

We have to enable advertising in mgmt_powered if broadcaster mode is on.

We also need to update the advertising data in mgmt_powered if brodcaster
mode is on.

As the advertising data is already being updated on mgmt_powered function,
we don't need to update it also in hci_dev_open.

Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
---
 net/bluetooth/hci_core.c |  3 ---
 net/bluetooth/mgmt.c     | 38 ++++++++++++++++++++++++--------------
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c692b14..518c916 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -764,9 +764,6 @@ int hci_dev_open(__u16 dev)
 		hci_dev_hold(hdev);
 		set_bit(HCI_UP, &hdev->flags);
 		hci_notify(hdev, HCI_DEV_UP);
-		hci_dev_lock(hdev);
-		__hci_update_ad(hdev);
-		hci_dev_unlock(hdev);
 		if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
 		    mgmt_valid_hdev(hdev)) {
 			hci_dev_lock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e910b11..805ae3b 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2720,12 +2720,6 @@ static int set_controller_data(struct sock *sk, struct hci_dev *hdev,
 
 	hci_dev_lock(hdev);
 
-	if (!hdev_is_powered(hdev)) {
-		hci_dev_unlock(hdev);
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA,
-				  MGMT_STATUS_NOT_POWERED);
-	}
-
 	room = HCI_MAX_AD_LENGTH - hdev->broadcast_data_len;
 	if (sizeof(cp->length) + sizeof(cp->type) + cp->length > room) {
 		hci_dev_unlock(hdev);
@@ -2757,12 +2751,6 @@ static int unset_controller_data(struct sock *sk, struct hci_dev *hdev,
 
 	hci_dev_lock(hdev);
 
-	if (!hdev_is_powered(hdev)) {
-		hci_dev_unlock(hdev);
-		return cmd_status(sk, hdev->id, MGMT_OP_UNSET_CONTROLLER_DATA,
-				  MGMT_STATUS_NOT_POWERED);
-	}
-
 	removed = hci_broadcast_data_remove(hdev, cp->type);
 
 	if (removed && test_bit(HCI_BROADCASTER, &hdev->dev_flags))
@@ -2784,8 +2772,20 @@ static int set_broadcaster_le(struct sock *sk, struct hci_dev *hdev, u8 enable)
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, hdev->id, MGMT_OP_SET_BROADCASTER,
-				  MGMT_STATUS_NOT_POWERED);
+		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;
 	}
 
@@ -3068,6 +3068,16 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
 				hci_send_cmd(hdev,
 					     HCI_OP_WRITE_LE_HOST_SUPPORTED,
 					     sizeof(cp), &cp);
+
+			__hci_update_ad(hdev);
+
+			if (test_bit(HCI_BROADCASTER, &hdev->dev_flags)) {
+				u8 enable = 1;
+				hdev->le_adv_req_reason =
+						LE_ADV_REQ_REASON_BROADCASTER;
+				hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE,
+					     sizeof(enable), &enable);
+			}
 		}
 
 		if (lmp_bredr_capable(hdev)) {
-- 
1.8.0.2


^ permalink raw reply related

* [PATCH 10/12] Bluetooth: Refactor le scan helpers to enable observer support
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <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 to 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 d5fd56a..8731add 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -121,6 +121,11 @@ struct le_scan_params {
 	u16 interval;
 	u16 window;
 	int timeout;
+	u8 reason;
+};
+
+enum {
+	LE_SCAN_REQ_REASON_DISCOVERY,
 };
 
 struct broadcast_data {
@@ -289,6 +294,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;
 	__u8			adv_data[HCI_MAX_AD_LENGTH];
@@ -1180,9 +1186,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 518c916..9b6c9e4 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1654,20 +1654,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);
@@ -1679,38 +1679,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;
 }
@@ -1736,11 +1750,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;
 
@@ -1756,6 +1770,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 805ae3b..bed28e4 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2377,7 +2377,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;
@@ -2385,8 +2386,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;
@@ -2443,7 +2444,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.8.0.2


^ permalink raw reply related

* [PATCH 11/12] Bluetooth: Add set observer MGMT command
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <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.

Some changes on device lock are needed. Moving hci_dev_lock from
mgmt_interleaved_discovery to hci_cc_le_set_scan_enable.

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             | 137 ++++++++++++++++++++++++++++++++++++---
 6 files changed, 179 insertions(+), 35 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index efbdd3d..c17bb9a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -122,6 +122,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 8731add..a82d6be 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 {
@@ -125,7 +127,9 @@ struct le_scan_params {
 };
 
 enum {
+	LE_SCAN_REQ_REASON_RESET,
 	LE_SCAN_REQ_REASON_DISCOVERY,
+	LE_SCAN_REQ_REASON_OBSERVER,
 };
 
 struct broadcast_data {
@@ -1136,6 +1140,7 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
 int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
 int mgmt_set_broadcaster_complete(struct hci_dev *hdev, bool changed,
 				  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 9b6c9e4..32bf2eb 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1672,14 +1672,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 b5eb89a..ede0b78 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1277,42 +1277,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;
 
@@ -1320,6 +1320,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 bed28e4..e960da2 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 */
@@ -395,6 +397,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
 	if (lmp_le_capable(hdev)) {
 		settings |= MGMT_SETTING_LE;
 		settings |= MGMT_SETTING_BROADCASTER;
+		settings |= MGMT_SETTING_OBSERVER;
 	}
 
 	return settings;
@@ -425,6 +428,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;
 
@@ -2318,14 +2324,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;
 }
 
@@ -2352,7 +2354,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;
@@ -2376,8 +2378,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;
@@ -2385,8 +2388,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;
@@ -2834,6 +2838,77 @@ 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)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_OBSERVER,
+				 MGMT_STATUS_NOT_POWERED);
+		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);
@@ -2884,6 +2959,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 },
 };
 
 
@@ -3777,6 +3853,42 @@ int mgmt_set_broadcaster_complete(struct hci_dev *hdev, bool changed, u8 status)
 	return err;
 }
 
+int mgmt_set_observer_complete(struct hci_dev *hdev, u8 enable, u8 status)
+{
+	struct pending_cmd *cmd;
+	struct cmd_lookup match = { NULL, hdev };
+	bool changed = false;
+	int err = 0;
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_OBSERVER, hdev);
+	if (!cmd)
+		return -ENOENT;
+
+	if (status) {
+		u8 mgmt_err = mgmt_status(status);
+		cmd_status_rsp(cmd, &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;
+	}
+
+	settings_rsp(cmd, &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)
@@ -3893,6 +4005,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.8.0.2


^ permalink raw reply related

* [PATCH 12/12] Bluetooth: Enable support for observer mode when powered off.
From: Jefferson Delfes @ 2012-12-14 18:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Aloisio Almeida Jr
In-Reply-To: <1355511098-10190-1-git-send-email-jefferson.delfes@openbossa.org>

From: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>

We have to enable le scan in mgmt_powered if observer mode is on.

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

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e960da2..04407d6 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2848,8 +2848,20 @@ static int set_observer_le(struct sock *sk, struct hci_dev *hdev, u8 enable)
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, hdev->id, MGMT_OP_SET_OBSERVER,
-				 MGMT_STATUS_NOT_POWERED);
+		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;
 	}
 
@@ -3156,6 +3168,13 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
 				hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE,
 					     sizeof(enable), &enable);
 			}
+
+			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);
+			}
 		}
 
 		if (lmp_bredr_capable(hdev)) {
-- 
1.8.0.2


^ permalink raw reply related

* [PATCH BlueZ 1/4] obex-client: Port MAP module to use D-Bus properties interface
From: Luiz Augusto von Dentz @ 2012-12-14 21:31 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 obexd/client/map.c | 315 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 178 insertions(+), 137 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index dcbcc8b..9cae20e 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -107,7 +107,7 @@ struct map_msg {
 	uint64_t size;
 	char *status;
 	uint8_t flags;
-	DBusMessage *msg;
+	GDBusPendingPropertySet pending;
 };
 
 struct map_parser {
@@ -421,176 +421,205 @@ static void set_message_status_cb(struct obc_session *session,
 						GError *err, void *user_data)
 {
 	struct map_msg *msg = user_data;
-	DBusMessage *reply;
 
 	if (err != NULL) {
-		reply = g_dbus_create_error(msg->msg,
+		g_dbus_pending_property_error(msg->pending,
 						ERROR_INTERFACE ".Failed",
 						"%s", err->message);
 		goto done;
 	}
 
-	reply = dbus_message_new_method_return(msg->msg);
-	if (reply == NULL) {
-		reply = g_dbus_create_error(msg->msg,
-						ERROR_INTERFACE ".Failed",
-						"%s", err->message);
-	}
+	g_dbus_pending_property_success(msg->pending);
 
 done:
-	g_dbus_send_message(conn, reply);
-	dbus_message_unref(msg->msg);
-	msg->msg = NULL;
+	msg->pending = 0;
 }
 
-static DBusMessage *map_msg_set_property(DBusConnection *connection,
-						DBusMessage *message,
-						void *user_data)
+static gboolean get_subject(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
 {
-	struct map_msg *msg = user_data;
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->subject);
+
+	return TRUE;
+}
+
+static gboolean get_timestamp(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->timestamp);
+
+	return TRUE;
+}
+
+static gboolean get_sender(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->sender);
+
+	return TRUE;
+}
+
+static gboolean get_sender_address(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+							&msg->sender_address);
+
+	return TRUE;
+}
+
+static gboolean get_replyto(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->replyto);
+
+	return TRUE;
+}
+
+static gboolean get_recipient(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->recipient);
+
+	return TRUE;
+}
+
+static gboolean get_recipient_address(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+						&msg->recipient_address);
+
+	return TRUE;
+}
+
+static gboolean get_type(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->type);
+
+	return TRUE;
+}
+
+static gboolean get_size(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_msg *msg = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &msg->size);
+
+	return TRUE;
+}
+
+static gboolean get_flag(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, uint8_t flag,
+					void *data)
+{
+	struct map_msg *msg = data;
+	dbus_bool_t value = (msg->flags & flag) != 0;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+
+	return TRUE;
+}
+
+static gboolean get_priority(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	return get_flag(property, iter, MAP_MSG_FLAG_PRIORITY, data);
+}
+
+static gboolean get_read(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	return get_flag(property, iter, MAP_MSG_FLAG_READ, data);
+}
+
+static gboolean get_sent(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	return get_flag(property, iter, MAP_MSG_FLAG_SENT, data);
+}
+
+static gboolean get_protected(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	return get_flag(property, iter, MAP_MSG_FLAG_PROTECTED, data);
+}
+
+static void set_status(const GDBusPropertyTable *property,
+			DBusMessageIter *iter, GDBusPendingPropertySet id,
+			uint8_t status, void *data)
+{
+	struct map_msg *msg = data;
 	struct obc_transfer *transfer;
-	char *property;
-	gboolean status;
+	gboolean value;
 	GError *err = NULL;
-	DBusMessage *reply;
 	GObexApparam *apparam;
 	char contents[2];
-	int op;
-	DBusMessageIter args, variant;
 
-	dbus_message_iter_init(message, &args);
-	if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING)
-		return g_dbus_create_error(message,
-				ERROR_INTERFACE ".InvalidArguments", NULL);
-
-	dbus_message_iter_get_basic(&args, &property);
-	dbus_message_iter_next(&args);
-	if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_VARIANT)
-		return g_dbus_create_error(message,
-				ERROR_INTERFACE ".InvalidArguments", NULL);
-
-	dbus_message_iter_recurse(&args, &variant);
-	if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_BOOLEAN)
-		return g_dbus_create_error(message,
-				ERROR_INTERFACE ".InvalidArguments", NULL);
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
+		return g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InvalidArguments",
+					"Invalid arguments in method call");
 
-	dbus_message_iter_get_basic(&variant, &status);
-
-	/* MAP supports modifying only these two properties. */
-	if (property && strcasecmp(property, "Read") == 0) {
-		op = STATUS_READ;
-		if (status)
-			msg->flags |= MAP_MSG_FLAG_READ;
-		else
-			msg->flags &= ~MAP_MSG_FLAG_READ;
-	} else if (property && strcasecmp(property, "Deleted") == 0)
-		op = STATUS_DELETE;
-	else {
-		return g_dbus_create_error(message,
-				ERROR_INTERFACE ".InvalidArguments", NULL);
-	}
+	dbus_message_iter_get_basic(iter, &value);
 
 	contents[0] = FILLER_BYTE;
 	contents[1] = '\0';
 
 	transfer = obc_transfer_put("x-bt/messageStatus", msg->handle, NULL,
-							contents,
-							sizeof(contents), &err);
+					contents, sizeof(contents), &err);
 	if (transfer == NULL)
 		goto fail;
 
 	apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_STATUSINDICATOR,
-								op);
-	apparam = g_obex_apparam_set_uint8(apparam, MAP_AP_STATUSVALUE,
 								status);
+	apparam = g_obex_apparam_set_uint8(apparam, MAP_AP_STATUSVALUE,
+								value);
 	obc_transfer_set_apparam(transfer, apparam);
 
 	if (!obc_session_queue(msg->data->session, transfer,
 				set_message_status_cb, msg, &err))
 		goto fail;
 
-	msg->msg = dbus_message_ref(message);
-	return NULL;
+	msg->pending = id;
+	return;
 
 fail:
-	reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+	g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed", "%s",
 								err->message);
 	g_error_free(err);
-	return reply;
 }
 
-static DBusMessage *map_msg_get_properties(DBusConnection *connection,
-						DBusMessage *message,
-						void *user_data)
+static void set_read(const GDBusPropertyTable *property,
+			DBusMessageIter *iter, GDBusPendingPropertySet id,
+			void *data)
 {
-	struct map_msg *msg = user_data;
-	GError *err = NULL;
-	DBusMessage *reply;
-	DBusMessageIter iter, data_array;
-	gboolean flag;
-
-	reply = dbus_message_new_method_return(message);
-	if (reply == NULL) {
-		reply = g_dbus_create_error(message,
-						ERROR_INTERFACE ".Failed",
-						NULL);
-		goto done;
-	}
-
-	dbus_message_iter_init_append(reply, &iter);
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-					DBUS_TYPE_STRING_AS_STRING
-					DBUS_TYPE_VARIANT_AS_STRING
-					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
-					&data_array);
-
-
-	obex_dbus_dict_append(&data_array, "Subject",
-				DBUS_TYPE_STRING, &msg->subject);
-	obex_dbus_dict_append(&data_array, "Timestamp",
-				DBUS_TYPE_STRING, &msg->timestamp);
-	obex_dbus_dict_append(&data_array, "Sender",
-				DBUS_TYPE_STRING, &msg->sender);
-	obex_dbus_dict_append(&data_array, "SenderAddress",
-				DBUS_TYPE_STRING, &msg->sender_address);
-	obex_dbus_dict_append(&data_array, "ReplyTo",
-				DBUS_TYPE_STRING, &msg->replyto);
-	obex_dbus_dict_append(&data_array, "Recipient",
-				DBUS_TYPE_STRING, &msg->recipient);
-	obex_dbus_dict_append(&data_array, "RecipientAddress",
-				DBUS_TYPE_STRING, &msg->recipient_address);
-	obex_dbus_dict_append(&data_array, "Type",
-				DBUS_TYPE_STRING, &msg->type);
-	obex_dbus_dict_append(&data_array, "Status",
-				DBUS_TYPE_STRING, &msg->status);
-	obex_dbus_dict_append(&data_array, "Size",
-				DBUS_TYPE_UINT64, &msg->size);
-
-	flag = (msg->flags & MAP_MSG_FLAG_PRIORITY) != 0;
-	obex_dbus_dict_append(&data_array, "Priority",
-				DBUS_TYPE_BOOLEAN, &flag);
-
-	flag = (msg->flags & MAP_MSG_FLAG_READ) != 0;
-	obex_dbus_dict_append(&data_array, "Read",
-				DBUS_TYPE_BOOLEAN, &flag);
-
-	flag = (msg->flags & MAP_MSG_FLAG_SENT) != 0;
-	obex_dbus_dict_append(&data_array, "Sent",
-				DBUS_TYPE_BOOLEAN, &flag);
-
-	flag = (msg->flags & MAP_MSG_FLAG_PROTECTED) != 0;
-	obex_dbus_dict_append(&data_array, "Protected",
-				DBUS_TYPE_BOOLEAN, &flag);
-
-	dbus_message_iter_close_container(&iter, &data_array);
-
-
-done:
-	if (err)
-		g_error_free(err);
+	set_status(property, iter, id, STATUS_READ, data);
+}
 
-	return reply;
+static void set_deleted(const GDBusPropertyTable *property,
+			DBusMessageIter *iter, GDBusPendingPropertySet id,
+			void *data)
+{
+	set_status(property, iter, id, STATUS_DELETE, data);
 }
 
 static const GDBusMethodTable map_msg_methods[] = {
@@ -600,13 +629,24 @@ static const GDBusMethodTable map_msg_methods[] = {
 			GDBUS_ARGS({ "transfer", "o" },
 						{ "properties", "a{sv}" }),
 			map_msg_get) },
-	{ GDBUS_METHOD("GetProperties",
-			NULL,
-			GDBUS_ARGS({ "properties", "a{sv}" }),
-			map_msg_get_properties) },
-	{ GDBUS_ASYNC_METHOD("SetProperty",
-			GDBUS_ARGS({ "property", "sv" }), NULL,
-			map_msg_set_property) },
+	{ }
+};
+
+static const GDBusPropertyTable map_msg_properties[] = {
+	{ "Subject", "s", get_subject },
+	{ "Timestamp", "s", get_timestamp },
+	{ "Sender", "s", get_sender },
+	{ "SenderAddress", "s", get_sender_address },
+	{ "ReplyTo", "s", get_replyto },
+	{ "Recipient", "s", get_recipient },
+	{ "RecipientAddress", "s", get_recipient_address },
+	{ "Type", "s", get_type },
+	{ "Size", "t", get_size },
+	{ "Priority", "b", get_priority },
+	{ "Read", "b", get_read, set_read },
+	{ "Sent", "b", get_sent },
+	{ "Protected", "b", get_sent },
+	{ "Deleted", "b", NULL, set_deleted },
 	{ }
 };
 
@@ -621,7 +661,8 @@ static struct map_msg *map_msg_create(struct map_data *data, const char *handle)
 					handle);
 
 	if (!g_dbus_register_interface(conn, msg->path, MAP_MSG_INTERFACE,
-						map_msg_methods, NULL, NULL,
+						map_msg_methods, NULL,
+						map_msg_properties,
 						msg, map_msg_free)) {
 		map_msg_free(msg);
 		return NULL;
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 2/4] obex-client: Port session code to use D-Bus properties interface
From: Luiz Augusto von Dentz @ 2012-12-14 21:31 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1355520720-11731-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 doc/obex-client-api.txt |  6 +---
 obexd/client/session.c  | 86 ++++++++++++++++++++++++++++---------------------
 2 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/doc/obex-client-api.txt b/doc/obex-client-api.txt
index 19c8541..f516760 100644
--- a/doc/obex-client-api.txt
+++ b/doc/obex-client-api.txt
@@ -43,11 +43,7 @@ Service		org.bluez.obex.client
 Interface	org.bluez.obex.Session
 Object path	[variable prefix]/{session0,session1,...}
 
-Methods		dict GetProperties()
-
-			Returns all properties for the session.
-
-		string GetCapabilities()
+Methods		string GetCapabilities()
 
 			Get remote device capabilities.
 
diff --git a/obexd/client/session.c b/obexd/client/session.c
index 2bac229..40d6c9c 100644
--- a/obexd/client/session.c
+++ b/obexd/client/session.c
@@ -524,39 +524,6 @@ void obc_session_shutdown(struct obc_session *session)
 	obc_session_unref(session);
 }
 
-static DBusMessage *session_get_properties(DBusConnection *connection,
-				DBusMessage *message, void *user_data)
-{
-	struct obc_session *session = user_data;
-	DBusMessage *reply;
-	DBusMessageIter iter, dict;
-
-	reply = dbus_message_new_method_return(message);
-	if (!reply)
-		return NULL;
-
-	dbus_message_iter_init_append(reply, &iter);
-
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-	if (session->source != NULL)
-		obex_dbus_dict_append(&dict, "Source", DBUS_TYPE_STRING,
-							&session->source);
-
-	obex_dbus_dict_append(&dict, "Destination", DBUS_TYPE_STRING,
-							&session->destination);
-
-	obex_dbus_dict_append(&dict, "Channel", DBUS_TYPE_BYTE,
-							&session->channel);
-
-	dbus_message_iter_close_container(&iter, &dict);
-
-	return reply;
-}
-
 static void capabilities_complete_callback(struct obc_session *session,
 						struct obc_transfer *transfer,
 						GError *err, void *user_data)
@@ -621,16 +588,63 @@ fail:
 
 }
 
+static gboolean get_source(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_session *session = data;
+
+	if (session->source == NULL)
+		return FALSE;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+							&session->source);
+
+	return TRUE;
+}
+
+static gboolean source_exists(const GDBusPropertyTable *property, void *data)
+{
+	struct obc_session *session = data;
+
+	return session->source != NULL;
+}
+
+static gboolean get_destination(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_session *session = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+							&session->destination);
+
+	return TRUE;
+}
+
+static gboolean get_channel(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_session *session = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+							&session->channel);
+
+	return TRUE;
+}
+
 static const GDBusMethodTable session_methods[] = {
-	{ GDBUS_METHOD("GetProperties",
-				NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-				session_get_properties) },
 	{ GDBUS_ASYNC_METHOD("GetCapabilities",
 				NULL, GDBUS_ARGS({ "capabilities", "s" }),
 				get_capabilities) },
 	{ }
 };
 
+static const GDBusPropertyTable session_properties[] = {
+	{ "Source", "s", get_source, NULL, source_exists },
+	{ "Destination", "s", get_destination },
+	{ "Channel", "y", get_channel },
+	{ }
+};
+
 static gboolean session_queue_complete(gpointer data)
 {
 	struct obc_session *session = data;
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 3/4] obex-client: Port transfer code to use D-Bus properties interface
From: Luiz Augusto von Dentz @ 2012-12-14 21:31 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1355520720-11731-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 doc/obex-client-api.txt | 12 --------
 obexd/client/transfer.c | 80 +++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 74 insertions(+), 18 deletions(-)

diff --git a/doc/obex-client-api.txt b/doc/obex-client-api.txt
index f516760..817ca71 100644
--- a/doc/obex-client-api.txt
+++ b/doc/obex-client-api.txt
@@ -535,18 +535,6 @@ Methods		object, dict Get(string targetfile, boolean attachment)
 			The properties of this transfer are also returned along
 			with the object path, to avoid a call to GetProperties.
 
-		dict GetProperties()
-
-			Returns all properties for the message. See the
-			properties section for available properties.
-
-		void SetProperty (string name, variant value)
-
-			Sets value to the mentioned property.
-
-			Possible properties: Read and Deleted.
-
-
 Properties	string Subject [readonly]
 
 			Message subject
diff --git a/obexd/client/transfer.c b/obexd/client/transfer.c
index 38c99cd..29d61f3 100644
--- a/obexd/client/transfer.c
+++ b/obexd/client/transfer.c
@@ -231,24 +231,91 @@ static DBusMessage *obc_transfer_cancel(DBusConnection *connection,
 	return NULL;
 }
 
+static gboolean get_name(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_transfer *transfer = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+							&transfer->name);
+
+	return TRUE;
+}
+
+static gboolean get_size(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_transfer *transfer = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64,
+							&transfer->size);
+
+	return TRUE;
+}
+
+static gboolean filename_exists(const GDBusPropertyTable *property, void *data)
+{
+	struct obc_transfer *transfer = data;
+
+	return transfer->filename != NULL;
+}
+
+static gboolean get_filename(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_transfer *transfer = data;
+
+	if (transfer->filename == NULL)
+		return FALSE;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+							&transfer->filename);
+
+	return TRUE;
+}
+
+static gboolean progress_exists(const GDBusPropertyTable *property, void *data)
+{
+	struct obc_transfer *transfer = data;
+
+	return transfer->obex != NULL;
+}
+
+static gboolean get_progress(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obc_transfer *transfer = data;
+
+	if (transfer->obex == NULL)
+		return FALSE;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64,
+							&transfer->progress);
+
+	return TRUE;
+}
+
 static const GDBusMethodTable obc_transfer_methods[] = {
-	{ GDBUS_METHOD("GetProperties",
-				NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-				obc_transfer_get_properties) },
 	{ GDBUS_ASYNC_METHOD("Cancel", NULL, NULL,
 				obc_transfer_cancel) },
 	{ }
 };
 
 static const GDBusSignalTable obc_transfer_signals[] = {
-	{ GDBUS_SIGNAL("PropertyChanged",
-		GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
 	{ GDBUS_SIGNAL("Complete", NULL) },
 	{ GDBUS_SIGNAL("Error",
 		GDBUS_ARGS({ "code", "s" }, { "message", "s" })) },
 	{ }
 };
 
+static const GDBusPropertyTable obc_transfer_properties[] = {
+	{ "Name", "s", get_name },
+	{ "Size", "t", get_size },
+	{ "Filename", "s", get_filename, NULL, filename_exists },
+	{ "Progress", "t", get_progress, NULL, progress_exists },
+	{ }
+};
+
 static void obc_transfer_free(struct obc_transfer *transfer)
 {
 	DBG("%p", transfer);
@@ -325,7 +392,8 @@ gboolean obc_transfer_register(struct obc_transfer *transfer,
 	if (g_dbus_register_interface(transfer->conn, transfer->path,
 				TRANSFER_INTERFACE,
 				obc_transfer_methods, obc_transfer_signals,
-				NULL, transfer, NULL) == FALSE) {
+				obc_transfer_properties, transfer,
+				NULL) == FALSE) {
 		g_set_error(err, OBC_TRANSFER_ERROR, -EFAULT,
 						"Unable to register to D-Bus");
 		return FALSE;
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 4/4] test: Update map-client to use D-Bus properties interface
From: Luiz Augusto von Dentz @ 2012-12-14 21:32 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1355520720-11731-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 test/map-client | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/map-client b/test/map-client
index 756ebb8..39dd79f 100755
--- a/test/map-client
+++ b/test/map-client
@@ -136,8 +136,8 @@ class MapClient:
 		self.map.ListMessages("", dict())
 		path = self.path + "/message" + handle
 		obj = bus.get_object("org.bluez.obex.client", path)
-		msg = dbus.Interface(obj, "org.bluez.obex.Message")
-		ret = msg.GetProperties()
+		msg = dbus.Interface(obj, "org.freedesktop.DBus.Properties")
+		ret = msg.GetAll("org.bluez.obex.Message")
 		print pformat(unwrap(ret))
 
 	def set_message_property(self, handle, prop, flag):
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH v2 1/5] device : Add EndGroupHandle key in attributes storage
From: Frédéric Danis @ 2012-12-15  8:59 UTC (permalink / raw)
  To: linux-bluetooth

End group handle should also be converted/saved for each
group in device's attributes file.
---
 doc/settings-storage.txt |    8 +++++---
 src/adapter.c            |    8 +++++---
 src/device.c             |   10 ++++++++++
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
index 351b17e..11b127f 100644
--- a/doc/settings-storage.txt
+++ b/doc/settings-storage.txt
@@ -94,10 +94,12 @@ Attributes are stored using their handle as group name (decimal format).
 
 Each group contains:
 
-  UUID		String		128-bit UUID of the attribute
+  UUID			String		128-bit UUID of the attribute
 
-  Value		String		Value of the attribute as hexadecimal encoded
-				string
+  Value			String		Value of the attribute as hexadecimal encoded
+					string
+
+  EndGroupHandle	Integer		End group handle in decimal format
 
 Sample:
   [1]
diff --git a/src/adapter.c b/src/adapter.c
index b962bc1..37e85ed 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2419,7 +2419,8 @@ static gboolean record_has_uuid(const sdp_record_t *rec,
 }
 
 static void store_attribute_uuid(GKeyFile *key_file, uint16_t start,
-					char *att_uuid, uuid_t uuid)
+					uint16_t end, char *att_uuid,
+					uuid_t uuid)
 {
 	char handle[6], uuid_str[33];
 	int i;
@@ -2443,6 +2444,7 @@ static void store_attribute_uuid(GKeyFile *key_file, uint16_t start,
 	sprintf(handle, "%hu", start);
 	g_key_file_set_string(key_file, handle, "UUID", att_uuid);
 	g_key_file_set_string(key_file, handle, "Value", uuid_str);
+	g_key_file_set_integer(key_file, handle, "EndGroupHandle", end);
 }
 
 static void store_sdp_record(char *local, char *peer, int handle, char *value)
@@ -2535,7 +2537,7 @@ static void convert_sdp_entry(char *key, char *value, void *user_data)
 	key_file = g_key_file_new();
 	g_key_file_load_from_file(key_file, filename, 0, NULL);
 
-	store_attribute_uuid(key_file, start, prim_uuid, uuid);
+	store_attribute_uuid(key_file, start, end, prim_uuid, uuid);
 
 	data = g_key_file_to_data(key_file, &length, NULL);
 	if (length > 0) {
@@ -2597,7 +2599,7 @@ static void convert_primaries_entry(char *key, char *value, void *user_data)
 		bt_string2uuid(&uuid, uuid_str);
 		sdp_uuid128_to_uuid(&uuid);
 
-		store_attribute_uuid(key_file, start, prim_uuid, uuid);
+		store_attribute_uuid(key_file, start, end, prim_uuid, uuid);
 	}
 
 	g_strfreev(services);
diff --git a/src/device.c b/src/device.c
index 77466ff..780a496 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1907,6 +1907,7 @@ static void load_att_info(struct btd_device *device, const gchar *local,
 
 	for (handle = groups; *handle; handle++) {
 		gboolean uuid_ok;
+		gint end;
 
 		str = g_key_file_get_string(key_file, *handle, "UUID", NULL);
 		if (!str)
@@ -1922,8 +1923,16 @@ static void load_att_info(struct btd_device *device, const gchar *local,
 		if (!str)
 			continue;
 
+		end = g_key_file_get_integer(key_file, *handle,
+						"EndGroupHandle", NULL);
+		if (end == 0) {
+			g_free(str);
+			continue;
+		}
+
 		prim = g_new0(struct gatt_primary, 1);
 		prim->range.start = atoi(*handle);
+		prim->range.end = end;
 
 		switch (strlen(str)) {
 		case 4:
@@ -2524,6 +2533,7 @@ static void store_primaries_from_sdp_record(GKeyFile *key_file,
 
 	g_key_file_set_string(key_file, handle, "UUID", prim_uuid);
 	g_key_file_set_string(key_file, handle, "Value", uuid_str);
+	g_key_file_set_integer(key_file, handle, "EndGroupHandle", end);
 
 done:
 	g_free(prim_uuid);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 2/5] device: Store services in device's attributes file
From: Frédéric Danis @ 2012-12-15  8:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1355561991-7906-1-git-send-email-frederic.danis@linux.intel.com>

Remove no more used write_device_primaries() from storage.[ch].
---
 src/device.c  |   73 +++++++++++++++++++++++++++++++++++++++++----------------
 src/storage.c |   15 ------------
 src/storage.h |    2 --
 3 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/src/device.c b/src/device.c
index 780a496..d6a6f04 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2872,37 +2872,70 @@ static void init_browse(struct browse_req *req, gboolean reverse)
 						l->data);
 }
 
-static char *primary_list_to_string(GSList *primary_list)
+static void store_services(struct btd_device *device)
 {
-	GString *services;
+	struct btd_adapter *adapter = device->adapter;
+	char filename[PATH_MAX + 1];
+	char src_addr[18], dst_addr[18];
+	uuid_t uuid;
+	char *prim_uuid;
+	GKeyFile *key_file;
 	GSList *l;
+	char *data;
+	gsize length = 0;
 
-	services = g_string_new(NULL);
+	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+	prim_uuid = bt_uuid2string(&uuid);
 
-	for (l = primary_list; l; l = l->next) {
-		struct gatt_primary *primary = l->data;
-		char service[64];
+	ba2str(adapter_get_address(adapter), src_addr);
+	ba2str(&device->bdaddr, dst_addr);
 
-		memset(service, 0, sizeof(service));
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/attributes", src_addr,
+								dst_addr);
+	filename[PATH_MAX] = '\0';
 
-		snprintf(service, sizeof(service), "%04X#%04X#%s ",
-				primary->range.start, primary->range.end, primary->uuid);
+	key_file = g_key_file_new();
 
-		services = g_string_append(services, service);
-	}
+	for (l = device->primaries; l; l = l->next) {
+		struct gatt_primary *primary = l->data;
+		char handle[6], uuid_str[33];
+		int i;
 
-	return g_string_free(services, FALSE);
-}
+		sprintf(handle, "%hu", primary->range.start);
 
-static void store_services(struct btd_device *device)
-{
-	struct btd_adapter *adapter = device->adapter;
-	char *str = primary_list_to_string(device->primaries);
+		bt_string2uuid(&uuid, primary->uuid);
+		sdp_uuid128_to_uuid(&uuid);
 
-	write_device_primaries(adapter_get_address(adapter), &device->bdaddr,
-						device->bdaddr_type, str);
+		switch (uuid.type) {
+		case SDP_UUID16:
+			sprintf(uuid_str, "%4.4X", uuid.value.uuid16);
+			break;
+		case SDP_UUID32:
+			sprintf(uuid_str, "%8.8X", uuid.value.uuid32);
+			break;
+		case SDP_UUID128:
+			for (i = 0; i < 16; i++)
+				sprintf(uuid_str + (i * 2), "%2.2X",
+						uuid.value.uuid128.data[i]);
+			break;
+		default:
+			uuid_str[0] = '\0';
+		}
 
-	g_free(str);
+		g_key_file_set_string(key_file, handle, "UUID", prim_uuid);
+		g_key_file_set_string(key_file, handle, "Value", uuid_str);
+		g_key_file_set_integer(key_file, handle, "EndGroupHandle",
+					primary->range.end);
+	}
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+	if (length > 0) {
+		create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+		g_file_set_contents(filename, data, length, NULL);
+	}
+
+	g_free(data);
+	g_key_file_free(key_file);
 }
 
 static void attio_connected(gpointer data, gpointer user_data)
diff --git a/src/storage.c b/src/storage.c
index 713a421..02ac1f3 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -273,21 +273,6 @@ int read_device_pairable(const bdaddr_t *bdaddr, gboolean *mode)
 	return 0;
 }
 
-int write_device_primaries(const bdaddr_t *sba, const bdaddr_t *dba,
-			  uint8_t bdaddr_type, const char *services)
-{
-	char filename[PATH_MAX + 1], key[20];
-
-	create_filename(filename, PATH_MAX, sba, "primaries");
-
-	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
-	ba2str(dba, key);
-	sprintf(&key[17], "#%hhu", bdaddr_type);
-
-	return textfile_put(filename, key, services);
-}
-
 static void filter_keys(char *key, char *value, void *data)
 {
 	struct match *match = data;
diff --git a/src/storage.h b/src/storage.h
index d150f15..682523a 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -35,8 +35,6 @@ ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin);
 sdp_record_t *record_from_string(const gchar *str);
 sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid);
 int read_device_pairable(const bdaddr_t *local, gboolean *mode);
-int write_device_primaries(const bdaddr_t *sba, const bdaddr_t *dba,
-				uint8_t bdaddr_type, const char *services);
 int read_device_ccc(const bdaddr_t *local, const bdaddr_t *peer,
 			uint8_t bdaddr_type, uint16_t handle, uint16_t *value);
 int write_device_ccc(const bdaddr_t *local, const bdaddr_t *peer,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 3/5] adapter: Convert ccc file
From: Frédéric Danis @ 2012-12-15  8:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1355561991-7906-1-git-send-email-frederic.danis@linux.intel.com>

Update settings-storage.txt documentation to add ccc file.
---
 doc/settings-storage.txt |   17 +++++++++++++
 src/adapter.c            |   63 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
index 11b127f..d1c3f4f 100644
--- a/doc/settings-storage.txt
+++ b/doc/settings-storage.txt
@@ -31,6 +31,8 @@ contains:
    contains:
     - an info file
     - an attributes file containing attributes of remote LE services
+    - a ccc file containing persistent Client Characteristic Configuration
+      (CCC) descriptor information for GATT characteristics
 
 So the directory structure is:
     /var/lib/bluetooth/<adapter address>/
@@ -43,6 +45,7 @@ So the directory structure is:
         ./<remote device address>/
             ./info
             ./attributes
+            ./ccc
         ./<remote device address>/
             ./info
             ./attributes
@@ -114,6 +117,20 @@ Sample:
   UUID=00002a00-0000-1000-8000-00805f9b34fb
   Value=4578616D706C6520446576696365
 
+CCC file format
+======================
+
+The ccc file stores the current CCC descriptor values for GATT characteristics
+which have notification/indication enabled by the remote device.
+
+Information is stored using CCC attribute handle as group name (in decimal
+format).
+
+Each group contains:
+
+  Value			String		CCC descriptor value encoded in
+					hexadecimal
+
 Cache directory file format
 ============================
 
diff --git a/src/adapter.c b/src/adapter.c
index 37e85ed..0dda57d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2636,6 +2636,56 @@ end:
 	g_key_file_free(key_file);
 }
 
+static void convert_ccc_entry(char *key, char *value, void *user_data)
+{
+	char *src_addr = user_data;
+	char dst_addr[18];
+	char type = BDADDR_BREDR;
+	int handle, ret;
+	char filename[PATH_MAX + 1];
+	GKeyFile *key_file;
+	struct stat st;
+	int err;
+	char group[6];
+	char *data;
+	gsize length = 0;
+
+	ret = sscanf(key, "%17s#%hhu#%04X", dst_addr, &type, &handle);
+	if (ret < 3)
+		return;
+
+	if (bachk(dst_addr) != 0)
+		return;
+
+	/* Check if the device directory has been created as records should
+	 * only be converted for known devices */
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s", src_addr, dst_addr);
+	filename[PATH_MAX] = '\0';
+
+	err = stat(filename, &st);
+	if (err || !S_ISDIR(st.st_mode))
+		return;
+
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/ccc", src_addr,
+								dst_addr);
+	filename[PATH_MAX] = '\0';
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+	sprintf(group, "%hu", handle);
+	g_key_file_set_string(key_file, group, "Value", value);
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+	if (length > 0) {
+		create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+		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];
@@ -2706,6 +2756,19 @@ static void convert_device_storage(struct btd_adapter *adapter)
 		textfile_put(filename, "converted", "yes");
 	}
 	free(str);
+
+	/* Convert ccc */
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/ccc", address);
+	filename[PATH_MAX] = '\0';
+
+	str = textfile_get(filename, "converted");
+	if (str && strcmp(str, "yes") == 0) {
+		DBG("Legacy %s file already converted", filename);
+	} else {
+		textfile_foreach(filename, convert_ccc_entry, address);
+		textfile_put(filename, "converted", "yes");
+	}
+	free(str);
 }
 
 static void convert_config(struct btd_adapter *adapter, const char *filename,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 4/5] device: Add btd_device_get_storage_path()
From: Frédéric Danis @ 2012-12-15  8:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1355561991-7906-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/device.c |   15 +++++++++++++++
 src/device.h |    2 ++
 2 files changed, 17 insertions(+)

diff --git a/src/device.c b/src/device.c
index d6a6f04..0bc8a09 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2049,6 +2049,21 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 	return btd_device_ref(device);
 }
 
+char *btd_device_get_storage_path(struct btd_device *device,
+				const char *filename)
+{
+	char srcaddr[18], dstaddr[18];
+
+	ba2str(adapter_get_address(device->adapter), srcaddr);
+	ba2str(&device->bdaddr, dstaddr);
+
+	if (!filename)
+		return g_strdup_printf(STORAGEDIR "/%s/%s", srcaddr, dstaddr);
+
+	return g_strdup_printf(STORAGEDIR "/%s/%s/%s", srcaddr, dstaddr,
+							filename);
+}
+
 void device_set_name(struct btd_device *device, const char *name)
 {
 	if (strncmp(name, device->name, MAX_NAME_LENGTH) == 0)
diff --git a/src/device.h b/src/device.h
index 8534117..7707bce 100644
--- a/src/device.h
+++ b/src/device.h
@@ -30,6 +30,8 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 				const char *address, uint8_t bdaddr_type);
 struct btd_device *device_create_from_storage(struct btd_adapter *adapter,
 				const char *address, GKeyFile *key_file);
+char *btd_device_get_storage_path(struct btd_device *device,
+				const char *filename);
 
 void device_set_name(struct btd_device *device, const char *name);
 void device_get_name(struct btd_device *device, char *name, size_t len);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 5/5] attrib-server: Read/write CCC info from new storage
From: Frédéric Danis @ 2012-12-15  8:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1355561991-7906-1-git-send-email-frederic.danis@linux.intel.com>

Remove no more used storage functions.
---
 src/attrib-server.c |   79 +++++++++++++++++++++++++++++++++++++---------
 src/storage.c       |   87 ---------------------------------------------------
 src/storage.h       |    6 ----
 3 files changed, 64 insertions(+), 108 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 8dc0d6a..e3715e8 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <glib.h>
+#include <sys/file.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/uuid.h>
@@ -746,6 +747,36 @@ static uint16_t find_by_type(struct gatt_channel *channel, uint16_t start,
 	return len;
 }
 
+static int read_device_ccc(struct btd_device *device, uint16_t handle,
+				uint16_t *value)
+{
+	char *filename;
+	GKeyFile *key_file;
+	char group[6];
+	char *str;
+	unsigned int config;
+	int err = 0;
+
+	filename = btd_device_get_storage_path(device, "ccc");
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+	sprintf(group, "%hu", handle);
+
+	str = g_key_file_get_string(key_file, group, "Value", NULL);
+	if (!str || sscanf(str, "%04X", &config) != 1)
+		err = -ENOENT;
+	else
+		*value = config;
+
+	g_free(str);
+	g_free(filename);
+	g_key_file_free(key_file);
+
+	return err;
+}
+
 static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 						uint8_t *pdu, size_t len)
 {
@@ -753,7 +784,6 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 	uint8_t status;
 	GList *l;
 	uint16_t cccval;
-	uint8_t bdaddr_type;
 	guint h = handle;
 
 	l = g_list_find_custom(channel->server->database,
@@ -764,11 +794,8 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 
 	a = l->data;
 
-	bdaddr_type = device_get_addr_type(channel->device);
-
 	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) == 0 &&
-		read_device_ccc(&channel->src, &channel->dst, bdaddr_type,
-							handle, &cccval) == 0) {
+		read_device_ccc(channel->device, handle, &cccval) == 0) {
 		uint8_t config[2];
 
 		att_put_u16(cccval, config);
@@ -794,7 +821,6 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 	uint8_t status;
 	GList *l;
 	uint16_t cccval;
-	uint8_t bdaddr_type;
 	guint h = handle;
 
 	l = g_list_find_custom(channel->server->database,
@@ -809,11 +835,8 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 		return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle,
 					ATT_ECODE_INVALID_OFFSET, pdu, len);
 
-	bdaddr_type = device_get_addr_type(channel->device);
-
 	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) == 0 &&
-		read_device_ccc(&channel->src, &channel->dst, bdaddr_type,
-							handle, &cccval) == 0) {
+		read_device_ccc(channel->device, handle, &cccval) == 0) {
 		uint8_t config[2];
 
 		att_put_u16(cccval, config);
@@ -869,10 +892,31 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 		}
 	} else {
 		uint16_t cccval = att_get_u16(value);
-		uint8_t bdaddr_type = device_get_addr_type(channel->device);
+		char *filename;
+		GKeyFile *key_file;
+		char group[6], value[5];
+		char *data;
+		gsize length = 0;
+
+		filename = btd_device_get_storage_path(channel->device, "ccc");
+
+		key_file = g_key_file_new();
+		g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+		sprintf(group, "%hu", handle);
+		sprintf(value, "%hhX", cccval);
+		g_key_file_set_string(key_file, group, "Value", value);
+
+		data = g_key_file_to_data(key_file, &length, NULL);
+		if (length > 0) {
+			create_file(filename,
+					S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+			g_file_set_contents(filename, data, length, NULL);
+		}
 
-		write_device_ccc(&channel->src, &channel->dst, bdaddr_type,
-								handle, cccval);
+		g_free(data);
+		g_free(filename);
+		g_key_file_free(key_file);
 	}
 
 	return enc_write_resp(pdu, len);
@@ -1089,8 +1133,13 @@ guint attrib_channel_attach(GAttrib *attrib)
 	ba2str(&channel->dst, addr);
 
 	device = adapter_find_device(server->adapter, addr);
-	if (device == NULL || device_is_bonded(device) == FALSE)
-		delete_device_ccc(&channel->src, &channel->dst);
+	if (device == NULL || device_is_bonded(device) == FALSE) {
+		char *filename;
+
+		filename = btd_device_get_storage_path(channel->device, "ccc");
+		unlink(filename);
+		g_free(filename);
+	}
 
 	if (cid != ATT_CID) {
 		channel->le = FALSE;
diff --git a/src/storage.c b/src/storage.c
index 02ac1f3..38e5897 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -272,90 +272,3 @@ int read_device_pairable(const bdaddr_t *bdaddr, gboolean *mode)
 
 	return 0;
 }
-
-static void filter_keys(char *key, char *value, void *data)
-{
-	struct match *match = data;
-
-	if (strncasecmp(key, match->pattern, strlen(match->pattern)) == 0)
-		match->keys = g_slist_append(match->keys, g_strdup(key));
-}
-
-static void delete_by_pattern(const char *filename, char *pattern)
-{
-	struct match match;
-	GSList *l;
-	int err;
-
-	memset(&match, 0, sizeof(match));
-	match.pattern = pattern;
-
-	err = textfile_foreach(filename, filter_keys, &match);
-	if (err < 0)
-		goto done;
-
-	for (l = match.keys; l; l = l->next) {
-		const char *key = l->data;
-		textfile_del(filename, key);
-	}
-
-done:
-	g_slist_free_full(match.keys, g_free);
-}
-
-int read_device_ccc(const bdaddr_t *local, const bdaddr_t *peer,
-					uint8_t bdaddr_type, uint16_t handle,
-					uint16_t *value)
-{
-	char filename[PATH_MAX + 1], addr[18], key[25];
-	char *str;
-	unsigned int config;
-	int err = 0;
-
-	create_filename(filename, PATH_MAX, local, "ccc");
-
-	ba2str(peer, addr);
-	snprintf(key, sizeof(key), "%17s#%hhu#%04X", addr, bdaddr_type, handle);
-
-	str = textfile_caseget(filename, key);
-	if (str == NULL)
-		return -ENOENT;
-
-	if (sscanf(str, "%04X", &config) != 1)
-		err = -ENOENT;
-	else
-		*value = config;
-
-	free(str);
-
-	return err;
-}
-
-int write_device_ccc(const bdaddr_t *local, const bdaddr_t *peer,
-					uint8_t bdaddr_type, uint16_t handle,
-					uint16_t value)
-{
-	char filename[PATH_MAX + 1], addr[18], key[25], config[5];
-
-	create_filename(filename, PATH_MAX, local, "ccc");
-
-	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
-	ba2str(peer, addr);
-	snprintf(key, sizeof(key), "%17s#%hhu#%04X", addr, bdaddr_type, handle);
-
-	snprintf(config, sizeof(config), "%04X", value);
-
-	return textfile_put(filename, key, config);
-}
-
-void delete_device_ccc(const bdaddr_t *local, const bdaddr_t *peer)
-{
-	char filename[PATH_MAX + 1], addr[18];
-
-	ba2str(peer, addr);
-
-	/* Deleting all CCC values of a given address */
-	create_filename(filename, PATH_MAX, local, "ccc");
-	delete_by_pattern(filename, addr);
-}
diff --git a/src/storage.h b/src/storage.h
index 682523a..cc7f930 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -35,9 +35,3 @@ ssize_t read_pin_code(const bdaddr_t *local, const bdaddr_t *peer, char *pin);
 sdp_record_t *record_from_string(const gchar *str);
 sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid);
 int read_device_pairable(const bdaddr_t *local, gboolean *mode);
-int read_device_ccc(const bdaddr_t *local, const bdaddr_t *peer,
-			uint8_t bdaddr_type, uint16_t handle, uint16_t *value);
-int write_device_ccc(const bdaddr_t *local, const bdaddr_t *peer,
-					uint8_t bdaddr_type, uint16_t handle,
-					uint16_t value);
-void delete_device_ccc(const bdaddr_t *local, const bdaddr_t *peer);
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH BlueZ 1/2] core: Fix leftover signal for UUIDs property
From: Johan Hedberg @ 2012-12-16 11:25 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <1355494410-24627-1-git-send-email-lucas.demarchi@profusion.mobi>

Hi Lucas,

On Fri, Dec 14, 2012, Lucas De Marchi wrote:
> ---
>  src/device.c | 28 ++++++++--------------------
>  1 file changed, 8 insertions(+), 20 deletions(-)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH BlueZ 1/4] obex-client: Port MAP module to use D-Bus properties interface
From: Johan Hedberg @ 2012-12-16 11:28 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1355520720-11731-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Fri, Dec 14, 2012, Luiz Augusto von Dentz wrote:
> ---
>  obexd/client/map.c | 315 ++++++++++++++++++++++++++++++-----------------------
>  1 file changed, 178 insertions(+), 137 deletions(-)

All patches in this set have been applied. Thanks.

Johan

^ permalink raw reply


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