aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Guedes <andre.guedes@openbossa.org>2012-02-17 18:39:38 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-19 05:34:55 -0500
commit5e0452c00a2e4b04ec1482248c897dacf106f1df (patch)
tree34bbd940ed96cc736dcd8dd9311414f8f035839e
parent343f935bfa44189c68527102c409286b0cfc4526 (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.h2
-rw-r--r--net/bluetooth/hci_event.c13
-rw-r--r--net/bluetooth/mgmt.c47
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,
1019int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status); 1020int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
1020int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); 1021int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
1021int mgmt_discovering(struct hci_dev *hdev, u8 discovering); 1022int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
1023int mgmt_interleaved_discovery(struct hci_dev *hdev);
1022int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); 1024int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
1023int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); 1025int 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
2158static 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
2181int 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
2156static int start_discovery(struct sock *sk, u16 index, 2198static 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 }