aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaganath Kanakkassery <jaganath.k.os@gmail.com>2018-07-06 07:35:28 -0400
committerMarcel Holtmann <marcel@holtmann.org>2018-07-06 16:41:17 -0400
commita2344b9e3a8c5c2064306b0d99b0e9a6c4813c08 (patch)
tree640724bb9bb1f691efd66d60f8709a7b0c3d68d2
parent3baef810462746cd5a085c1e1416829d2af2622d (diff)
Bluetooth: Use extended scanning if controller supports
This implements Set extended scan param and set extended scan enable commands and use it for start LE scan based on controller support. The new features added in these commands are setting of new PHY for scanning and setting of scan duration. Both features are disabled for now, meaning only 1M PHY is set and scan duration is set to 0 which means that scanning will be done untill scan disable is called. < HCI Command: LE Set Extended Scan Parameters (0x08|0x0041) plen 8 Own address type: Random (0x01) Filter policy: Accept all advertisement (0x00) PHYs: 0x01 Entry 0: LE 1M Type: Active (0x01) Interval: 11.250 msec (0x0012) Window: 11.250 msec (0x0012) > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6 Extended scan: Enabled (0x01) Filter duplicates: Enabled (0x01) Duration: 0 msec (0x0000) Period: 0.00 sec (0x0000) > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci.h24
-rw-r--r--include/net/bluetooth/hci_core.h4
-rw-r--r--net/bluetooth/hci_event.c51
-rw-r--r--net/bluetooth/hci_request.c110
4 files changed, 164 insertions, 25 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 4af1a3a4d9b1..8c2868f439e7 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1514,6 +1514,30 @@ struct hci_cp_le_set_default_phy {
1514 __u8 rx_phys; 1514 __u8 rx_phys;
1515} __packed; 1515} __packed;
1516 1516
1517#define HCI_OP_LE_SET_EXT_SCAN_PARAMS 0x2041
1518struct hci_cp_le_set_ext_scan_params {
1519 __u8 own_addr_type;
1520 __u8 filter_policy;
1521 __u8 scanning_phys;
1522 __u8 data[0];
1523} __packed;
1524
1525#define LE_SCAN_PHY_1M 0x01
1526
1527struct hci_cp_le_scan_phy_params {
1528 __u8 type;
1529 __le16 interval;
1530 __le16 window;
1531} __packed;
1532
1533#define HCI_OP_LE_SET_EXT_SCAN_ENABLE 0x2042
1534struct hci_cp_le_set_ext_scan_enable {
1535 __u8 enable;
1536 __u8 filter_dup;
1537 __le16 duration;
1538 __le16 period;
1539} __packed;
1540
1517/* ---- HCI Events ---- */ 1541/* ---- HCI Events ---- */
1518#define HCI_EV_INQUIRY_COMPLETE 0x01 1542#define HCI_EV_INQUIRY_COMPLETE 0x01
1519 1543
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 409f49bd8338..cc0bde74dd45 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1158,6 +1158,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
1158#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \ 1158#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \
1159 hci_dev_test_flag(dev, HCI_SC_ENABLED)) 1159 hci_dev_test_flag(dev, HCI_SC_ENABLED))
1160 1160
1161/* Use ext scanning if set ext scan param and ext scan enable is supported */
1162#define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \
1163 ((dev)->commands[37] & 0x40))
1164
1161/* ----- HCI protocols ----- */ 1165/* ----- HCI protocols ----- */
1162#define HCI_PROTO_DEFER 0x01 1166#define HCI_PROTO_DEFER 0x01
1163 1167
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9ec07cd4ab13..15afad005d72 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1098,6 +1098,31 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1098 hci_dev_unlock(hdev); 1098 hci_dev_unlock(hdev);
1099} 1099}
1100 1100
1101static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev,
1102 struct sk_buff *skb)
1103{
1104 struct hci_cp_le_set_ext_scan_params *cp;
1105 __u8 status = *((__u8 *) skb->data);
1106 struct hci_cp_le_scan_phy_params *phy_param;
1107
1108 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1109
1110 if (status)
1111 return;
1112
1113 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS);
1114 if (!cp)
1115 return;
1116
1117 phy_param = (void *)cp->data;
1118
1119 hci_dev_lock(hdev);
1120
1121 hdev->le_scan_type = phy_param->type;
1122
1123 hci_dev_unlock(hdev);
1124}
1125
1101static bool has_pending_adv_report(struct hci_dev *hdev) 1126static bool has_pending_adv_report(struct hci_dev *hdev)
1102{ 1127{
1103 struct discovery_state *d = &hdev->discovery; 1128 struct discovery_state *d = &hdev->discovery;
@@ -1202,6 +1227,24 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
1202 le_set_scan_enable_complete(hdev, cp->enable); 1227 le_set_scan_enable_complete(hdev, cp->enable);
1203} 1228}
1204 1229
1230static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
1231 struct sk_buff *skb)
1232{
1233 struct hci_cp_le_set_ext_scan_enable *cp;
1234 __u8 status = *((__u8 *) skb->data);
1235
1236 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1237
1238 if (status)
1239 return;
1240
1241 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE);
1242 if (!cp)
1243 return;
1244
1245 le_set_scan_enable_complete(hdev, cp->enable);
1246}
1247
1205static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 1248static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
1206 struct sk_buff *skb) 1249 struct sk_buff *skb)
1207{ 1250{
@@ -3079,6 +3122,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
3079 hci_cc_write_ssp_debug_mode(hdev, skb); 3122 hci_cc_write_ssp_debug_mode(hdev, skb);
3080 break; 3123 break;
3081 3124
3125 case HCI_OP_LE_SET_EXT_SCAN_PARAMS:
3126 hci_cc_le_set_ext_scan_param(hdev, skb);
3127 break;
3128
3129 case HCI_OP_LE_SET_EXT_SCAN_ENABLE:
3130 hci_cc_le_set_ext_scan_enable(hdev, skb);
3131 break;
3132
3082 default: 3133 default:
3083 BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); 3134 BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3084 break; 3135 break;
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 76dcc3f14cea..faf7c711234c 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -647,11 +647,22 @@ void __hci_req_update_eir(struct hci_request *req)
647 647
648void hci_req_add_le_scan_disable(struct hci_request *req) 648void hci_req_add_le_scan_disable(struct hci_request *req)
649{ 649{
650 struct hci_cp_le_set_scan_enable cp; 650 struct hci_dev *hdev = req->hdev;
651 651
652 memset(&cp, 0, sizeof(cp)); 652 if (use_ext_scan(hdev)) {
653 cp.enable = LE_SCAN_DISABLE; 653 struct hci_cp_le_set_ext_scan_enable cp;
654 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); 654
655 memset(&cp, 0, sizeof(cp));
656 cp.enable = LE_SCAN_DISABLE;
657 hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_ENABLE, sizeof(cp),
658 &cp);
659 } else {
660 struct hci_cp_le_set_scan_enable cp;
661
662 memset(&cp, 0, sizeof(cp));
663 cp.enable = LE_SCAN_DISABLE;
664 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
665 }
655} 666}
656 667
657static void add_to_white_list(struct hci_request *req, 668static void add_to_white_list(struct hci_request *req,
@@ -770,23 +781,60 @@ static bool scan_use_rpa(struct hci_dev *hdev)
770static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval, 781static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval,
771 u16 window, u8 own_addr_type, u8 filter_policy) 782 u16 window, u8 own_addr_type, u8 filter_policy)
772{ 783{
773 struct hci_cp_le_set_scan_param param_cp; 784 struct hci_dev *hdev = req->hdev;
774 struct hci_cp_le_set_scan_enable enable_cp;
775
776 memset(&param_cp, 0, sizeof(param_cp));
777 param_cp.type = type;
778 param_cp.interval = cpu_to_le16(interval);
779 param_cp.window = cpu_to_le16(window);
780 param_cp.own_address_type = own_addr_type;
781 param_cp.filter_policy = filter_policy;
782 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
783 &param_cp);
784 785
785 memset(&enable_cp, 0, sizeof(enable_cp)); 786 /* Use ext scanning if set ext scan param and ext scan enable is
786 enable_cp.enable = LE_SCAN_ENABLE; 787 * supported
787 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; 788 */
788 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), 789 if (use_ext_scan(hdev)) {
789 &enable_cp); 790 struct hci_cp_le_set_ext_scan_params *ext_param_cp;
791 struct hci_cp_le_set_ext_scan_enable ext_enable_cp;
792 struct hci_cp_le_scan_phy_params *phy_params;
793 /* Ony single PHY (1M) is supported as of now */
794 u8 data[sizeof(*ext_param_cp) + sizeof(*phy_params) * 1];
795
796 ext_param_cp = (void *)data;
797 phy_params = (void *)ext_param_cp->data;
798
799 memset(ext_param_cp, 0, sizeof(*ext_param_cp));
800 ext_param_cp->own_addr_type = own_addr_type;
801 ext_param_cp->filter_policy = filter_policy;
802 ext_param_cp->scanning_phys = LE_SCAN_PHY_1M;
803
804 memset(phy_params, 0, sizeof(*phy_params));
805 phy_params->type = type;
806 phy_params->interval = cpu_to_le16(interval);
807 phy_params->window = cpu_to_le16(window);
808
809 hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_PARAMS,
810 sizeof(*ext_param_cp) + sizeof(*phy_params),
811 ext_param_cp);
812
813 memset(&ext_enable_cp, 0, sizeof(ext_enable_cp));
814 ext_enable_cp.enable = LE_SCAN_ENABLE;
815 ext_enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
816
817 hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_ENABLE,
818 sizeof(ext_enable_cp), &ext_enable_cp);
819 } else {
820 struct hci_cp_le_set_scan_param param_cp;
821 struct hci_cp_le_set_scan_enable enable_cp;
822
823 memset(&param_cp, 0, sizeof(param_cp));
824 param_cp.type = type;
825 param_cp.interval = cpu_to_le16(interval);
826 param_cp.window = cpu_to_le16(window);
827 param_cp.own_address_type = own_addr_type;
828 param_cp.filter_policy = filter_policy;
829 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
830 &param_cp);
831
832 memset(&enable_cp, 0, sizeof(enable_cp));
833 enable_cp.enable = LE_SCAN_ENABLE;
834 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
835 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
836 &enable_cp);
837 }
790} 838}
791 839
792void hci_req_add_le_passive_scan(struct hci_request *req) 840void hci_req_add_le_passive_scan(struct hci_request *req)
@@ -1948,7 +1996,6 @@ discov_stopped:
1948static int le_scan_restart(struct hci_request *req, unsigned long opt) 1996static int le_scan_restart(struct hci_request *req, unsigned long opt)
1949{ 1997{
1950 struct hci_dev *hdev = req->hdev; 1998 struct hci_dev *hdev = req->hdev;
1951 struct hci_cp_le_set_scan_enable cp;
1952 1999
1953 /* If controller is not scanning we are done. */ 2000 /* If controller is not scanning we are done. */
1954 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) 2001 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
@@ -1956,10 +2003,23 @@ static int le_scan_restart(struct hci_request *req, unsigned long opt)
1956 2003
1957 hci_req_add_le_scan_disable(req); 2004 hci_req_add_le_scan_disable(req);
1958 2005
1959 memset(&cp, 0, sizeof(cp)); 2006 if (use_ext_scan(hdev)) {
1960 cp.enable = LE_SCAN_ENABLE; 2007 struct hci_cp_le_set_ext_scan_enable ext_enable_cp;
1961 cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; 2008
1962 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); 2009 memset(&ext_enable_cp, 0, sizeof(ext_enable_cp));
2010 ext_enable_cp.enable = LE_SCAN_ENABLE;
2011 ext_enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
2012
2013 hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_ENABLE,
2014 sizeof(ext_enable_cp), &ext_enable_cp);
2015 } else {
2016 struct hci_cp_le_set_scan_enable cp;
2017
2018 memset(&cp, 0, sizeof(cp));
2019 cp.enable = LE_SCAN_ENABLE;
2020 cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
2021 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
2022 }
1963 2023
1964 return 0; 2024 return 0;
1965} 2025}