aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Guedes <andre.guedes@openbossa.org>2012-02-03 15:47:59 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-13 10:01:34 -0500
commit7ba8b4be38e7c83b2b13333a82a0ecde921a7390 (patch)
tree1ad9bb8b0eafed266538a2e238649149439ccc29
parent6fbe195dc41c4fae1fa7aca1a38c888de1d24e2d (diff)
Bluetooth: Add hci_do_le_scan()
This patch adds to hci_core the hci_do_le_scan function which should be used to scan LE devices. In order to enable LE scan, hci_do_le_scan() sends commands (Set LE Scan Parameters and Set LE Scan Enable) to the controller and waits for its results. If commands were executed successfully a delayed work is scheduled to disable the ongoing scanning after some amount of time. This function blocks. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
-rw-r--r--include/net/bluetooth/hci_core.h8
-rw-r--r--net/bluetooth/hci_core.c74
-rw-r--r--net/bluetooth/hci_event.c13
3 files changed, 92 insertions, 3 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bf2ef5667887..3e70872bffea 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -122,6 +122,12 @@ struct adv_entry {
122 u8 bdaddr_type; 122 u8 bdaddr_type;
123}; 123};
124 124
125struct le_scan_params {
126 u8 type;
127 u16 interval;
128 u16 window;
129};
130
125#define NUM_REASSEMBLY 4 131#define NUM_REASSEMBLY 4
126struct hci_dev { 132struct hci_dev {
127 struct list_head list; 133 struct list_head list;
@@ -261,6 +267,8 @@ struct hci_dev {
261 267
262 unsigned long dev_flags; 268 unsigned long dev_flags;
263 269
270 struct delayed_work le_scan_disable;
271
264 int (*open)(struct hci_dev *hdev); 272 int (*open)(struct hci_dev *hdev);
265 int (*close)(struct hci_dev *hdev); 273 int (*close)(struct hci_dev *hdev);
266 int (*flush)(struct hci_dev *hdev); 274 int (*flush)(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 1175f27bd445..ae86cdd80ac0 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -759,6 +759,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
759 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) 759 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
760 cancel_delayed_work(&hdev->service_cache); 760 cancel_delayed_work(&hdev->service_cache);
761 761
762 cancel_delayed_work_sync(&hdev->le_scan_disable);
763
762 hci_dev_lock(hdev); 764 hci_dev_lock(hdev);
763 inquiry_cache_flush(hdev); 765 inquiry_cache_flush(hdev);
764 hci_conn_hash_flush(hdev); 766 hci_conn_hash_flush(hdev);
@@ -1596,6 +1598,76 @@ int hci_add_adv_entry(struct hci_dev *hdev,
1596 return 0; 1598 return 0;
1597} 1599}
1598 1600
1601static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt)
1602{
1603 struct le_scan_params *param = (struct le_scan_params *) opt;
1604 struct hci_cp_le_set_scan_param cp;
1605
1606 memset(&cp, 0, sizeof(cp));
1607 cp.type = param->type;
1608 cp.interval = cpu_to_le16(param->interval);
1609 cp.window = cpu_to_le16(param->window);
1610
1611 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp);
1612}
1613
1614static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt)
1615{
1616 struct hci_cp_le_set_scan_enable cp;
1617
1618 memset(&cp, 0, sizeof(cp));
1619 cp.enable = 1;
1620
1621 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
1622}
1623
1624static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
1625 u16 window, int timeout)
1626{
1627 long timeo = msecs_to_jiffies(3000);
1628 struct le_scan_params param;
1629 int err;
1630
1631 BT_DBG("%s", hdev->name);
1632
1633 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1634 return -EINPROGRESS;
1635
1636 param.type = type;
1637 param.interval = interval;
1638 param.window = window;
1639
1640 hci_req_lock(hdev);
1641
1642 err = __hci_request(hdev, le_scan_param_req, (unsigned long) &param,
1643 timeo);
1644 if (!err)
1645 err = __hci_request(hdev, le_scan_enable_req, 0, timeo);
1646
1647 hci_req_unlock(hdev);
1648
1649 if (err < 0)
1650 return err;
1651
1652 schedule_delayed_work(&hdev->le_scan_disable,
1653 msecs_to_jiffies(timeout));
1654
1655 return 0;
1656}
1657
1658static void le_scan_disable_work(struct work_struct *work)
1659{
1660 struct hci_dev *hdev = container_of(work, struct hci_dev,
1661 le_scan_disable.work);
1662 struct hci_cp_le_set_scan_enable cp;
1663
1664 BT_DBG("%s", hdev->name);
1665
1666 memset(&cp, 0, sizeof(cp));
1667
1668 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
1669}
1670
1599/* Register HCI device */ 1671/* Register HCI device */
1600int hci_register_dev(struct hci_dev *hdev) 1672int hci_register_dev(struct hci_dev *hdev)
1601{ 1673{
@@ -1682,6 +1754,8 @@ int hci_register_dev(struct hci_dev *hdev)
1682 1754
1683 atomic_set(&hdev->promisc, 0); 1755 atomic_set(&hdev->promisc, 0);
1684 1756
1757 INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
1758
1685 write_unlock(&hci_dev_list_lock); 1759 write_unlock(&hci_dev_list_lock);
1686 1760
1687 hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND | 1761 hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8971c18205c0..97152d9d7116 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1031,6 +1031,8 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1031 __u8 status = *((__u8 *) skb->data); 1031 __u8 status = *((__u8 *) skb->data);
1032 1032
1033 BT_DBG("%s status 0x%x", hdev->name, status); 1033 BT_DBG("%s status 0x%x", hdev->name, status);
1034
1035 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
1034} 1036}
1035 1037
1036static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1038static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
@@ -1041,15 +1043,17 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1041 1043
1042 BT_DBG("%s status 0x%x", hdev->name, status); 1044 BT_DBG("%s status 0x%x", hdev->name, status);
1043 1045
1044 if (status)
1045 return;
1046
1047 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1046 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
1048 if (!cp) 1047 if (!cp)
1049 return; 1048 return;
1050 1049
1051 switch (cp->enable) { 1050 switch (cp->enable) {
1052 case LE_SCANNING_ENABLED: 1051 case LE_SCANNING_ENABLED:
1052 hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
1053
1054 if (status)
1055 return;
1056
1053 set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1057 set_bit(HCI_LE_SCAN, &hdev->dev_flags);
1054 1058
1055 cancel_delayed_work_sync(&hdev->adv_work); 1059 cancel_delayed_work_sync(&hdev->adv_work);
@@ -1061,6 +1065,9 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1061 break; 1065 break;
1062 1066
1063 case LE_SCANNING_DISABLED: 1067 case LE_SCANNING_DISABLED:
1068 if (status)
1069 return;
1070
1064 clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1071 clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
1065 1072
1066 hci_dev_lock(hdev); 1073 hci_dev_lock(hdev);