aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}