diff options
author | Andre Guedes <andre.guedes@openbossa.org> | 2012-02-17 18:39:38 -0500 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2012-02-19 05:34:55 -0500 |
commit | 5e0452c00a2e4b04ec1482248c897dacf106f1df (patch) | |
tree | 34bbd940ed96cc736dcd8dd9311414f8f035839e | |
parent | 343f935bfa44189c68527102c409286b0cfc4526 (diff) |
Bluetooth: Interleaved discovery support
This patch adds interleaved discovery support to MGMT Start
Discovery command.
In case interleaved discovery is not supported (not a dual mode
device), we perform BR/EDR or LE-only discovery according to the
device capabilities.
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.h | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 13 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 47 |
3 files changed, 57 insertions, 5 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 942de7764278..2aafeb3a8793 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -716,6 +716,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); | |||
716 | #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) | 716 | #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) |
717 | #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) | 717 | #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) |
718 | #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) | 718 | #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) |
719 | #define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR)) | ||
719 | 720 | ||
720 | /* ----- Extended LMP capabilities ----- */ | 721 | /* ----- Extended LMP capabilities ----- */ |
721 | #define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE) | 722 | #define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE) |
@@ -1019,6 +1020,7 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
1019 | int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status); | 1020 | int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status); |
1020 | int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); | 1021 | int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); |
1021 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering); | 1022 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering); |
1023 | int mgmt_interleaved_discovery(struct hci_dev *hdev); | ||
1022 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1024 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
1023 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 1025 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); |
1024 | 1026 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 9aea7b898821..04fb1f02dfcc 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1090,11 +1090,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1090 | 1090 | ||
1091 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); | 1091 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); |
1092 | 1092 | ||
1093 | hci_dev_lock(hdev); | ||
1094 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
1095 | hci_dev_unlock(hdev); | ||
1096 | |||
1097 | schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); | 1093 | schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); |
1094 | |||
1095 | if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) { | ||
1096 | mgmt_interleaved_discovery(hdev); | ||
1097 | } else { | ||
1098 | hci_dev_lock(hdev); | ||
1099 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
1100 | hci_dev_unlock(hdev); | ||
1101 | } | ||
1102 | |||
1098 | break; | 1103 | break; |
1099 | 1104 | ||
1100 | default: | 1105 | default: |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a9cd38dc2cab..89754bbcd02b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -108,8 +108,10 @@ static const u16 mgmt_events[] = { | |||
108 | #define LE_SCAN_WIN 0x12 | 108 | #define LE_SCAN_WIN 0x12 |
109 | #define LE_SCAN_INT 0x12 | 109 | #define LE_SCAN_INT 0x12 |
110 | #define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */ | 110 | #define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */ |
111 | #define LE_SCAN_TIMEOUT_BREDR_LE 5120 /* TGAP(100)/2 */ | ||
111 | 112 | ||
112 | #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */ | 113 | #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */ |
114 | #define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */ | ||
113 | 115 | ||
114 | #define SERVICE_CACHE_TIMEOUT (5 * 1000) | 116 | #define SERVICE_CACHE_TIMEOUT (5 * 1000) |
115 | 117 | ||
@@ -2153,6 +2155,46 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, | |||
2153 | return err; | 2155 | return err; |
2154 | } | 2156 | } |
2155 | 2157 | ||
2158 | static int discovery(struct hci_dev *hdev) | ||
2159 | { | ||
2160 | int err; | ||
2161 | |||
2162 | if (lmp_host_le_capable(hdev)) { | ||
2163 | if (lmp_bredr_capable(hdev)) { | ||
2164 | err = hci_le_scan(hdev, LE_SCAN_TYPE, | ||
2165 | LE_SCAN_INT, LE_SCAN_WIN, | ||
2166 | LE_SCAN_TIMEOUT_BREDR_LE); | ||
2167 | } else { | ||
2168 | hdev->discovery.type = DISCOV_TYPE_LE; | ||
2169 | err = hci_le_scan(hdev, LE_SCAN_TYPE, | ||
2170 | LE_SCAN_INT, LE_SCAN_WIN, | ||
2171 | LE_SCAN_TIMEOUT_LE_ONLY); | ||
2172 | } | ||
2173 | } else { | ||
2174 | hdev->discovery.type = DISCOV_TYPE_BREDR; | ||
2175 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); | ||
2176 | } | ||
2177 | |||
2178 | return err; | ||
2179 | } | ||
2180 | |||
2181 | int mgmt_interleaved_discovery(struct hci_dev *hdev) | ||
2182 | { | ||
2183 | int err; | ||
2184 | |||
2185 | BT_DBG("%s", hdev->name); | ||
2186 | |||
2187 | hci_dev_lock(hdev); | ||
2188 | |||
2189 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE); | ||
2190 | if (err < 0) | ||
2191 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
2192 | |||
2193 | hci_dev_unlock(hdev); | ||
2194 | |||
2195 | return err; | ||
2196 | } | ||
2197 | |||
2156 | static int start_discovery(struct sock *sk, u16 index, | 2198 | static int start_discovery(struct sock *sk, u16 index, |
2157 | void *data, u16 len) | 2199 | void *data, u16 len) |
2158 | { | 2200 | { |
@@ -2196,7 +2238,6 @@ static int start_discovery(struct sock *sk, u16 index, | |||
2196 | 2238 | ||
2197 | switch (hdev->discovery.type) { | 2239 | switch (hdev->discovery.type) { |
2198 | case DISCOV_TYPE_BREDR: | 2240 | case DISCOV_TYPE_BREDR: |
2199 | case DISCOV_TYPE_INTERLEAVED: | ||
2200 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); | 2241 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); |
2201 | break; | 2242 | break; |
2202 | 2243 | ||
@@ -2205,6 +2246,10 @@ static int start_discovery(struct sock *sk, u16 index, | |||
2205 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); | 2246 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); |
2206 | break; | 2247 | break; |
2207 | 2248 | ||
2249 | case DISCOV_TYPE_INTERLEAVED: | ||
2250 | err = discovery(hdev); | ||
2251 | break; | ||
2252 | |||
2208 | default: | 2253 | default: |
2209 | err = -EINVAL; | 2254 | err = -EINVAL; |
2210 | } | 2255 | } |