diff options
-rw-r--r-- | include/net/bluetooth/hci.h | 24 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 51 | ||||
-rw-r--r-- | net/bluetooth/hci_request.c | 110 |
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 | ||
1518 | struct 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 | |||
1527 | struct 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 | ||
1534 | struct 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 | ||
1101 | static 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 | |||
1101 | static bool has_pending_adv_report(struct hci_dev *hdev) | 1126 | static 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 | ||
1230 | static 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 | |||
1205 | static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, | 1248 | static 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 | ||
648 | void hci_req_add_le_scan_disable(struct hci_request *req) | 648 | void 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 | ||
657 | static void add_to_white_list(struct hci_request *req, | 668 | static void add_to_white_list(struct hci_request *req, |
@@ -770,23 +781,60 @@ static bool scan_use_rpa(struct hci_dev *hdev) | |||
770 | static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval, | 781 | static 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(¶m_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 | ¶m_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(¶m_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 | ¶m_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 | ||
792 | void hci_req_add_le_passive_scan(struct hci_request *req) | 840 | void hci_req_add_le_passive_scan(struct hci_request *req) |
@@ -1948,7 +1996,6 @@ discov_stopped: | |||
1948 | static int le_scan_restart(struct hci_request *req, unsigned long opt) | 1996 | static 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 | } |