Skip to content

Commit

Permalink
Bluetooth: Interleaved discovery support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andre Guedes authored and Johan Hedberg committed Feb 19, 2012
1 parent 343f935 commit 5e0452c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
2 changes: 2 additions & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))

/* ----- Extended LMP capabilities ----- */
#define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE)
Expand Down Expand Up @@ -1019,6 +1020,7 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_interleaved_discovery(struct hci_dev *hdev);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);

Expand Down
13 changes: 9 additions & 4 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1090,11 +1090,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,

clear_bit(HCI_LE_SCAN, &hdev->dev_flags);

hci_dev_lock(hdev);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);

schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);

if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
mgmt_interleaved_discovery(hdev);
} else {
hci_dev_lock(hdev);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);
}

break;

default:
Expand Down
47 changes: 46 additions & 1 deletion net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ static const u16 mgmt_events[] = {
#define LE_SCAN_WIN 0x12
#define LE_SCAN_INT 0x12
#define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */
#define LE_SCAN_TIMEOUT_BREDR_LE 5120 /* TGAP(100)/2 */

#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
#define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */

#define SERVICE_CACHE_TIMEOUT (5 * 1000)

Expand Down Expand Up @@ -2153,6 +2155,46 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
return err;
}

static int discovery(struct hci_dev *hdev)
{
int err;

if (lmp_host_le_capable(hdev)) {
if (lmp_bredr_capable(hdev)) {
err = hci_le_scan(hdev, LE_SCAN_TYPE,
LE_SCAN_INT, LE_SCAN_WIN,
LE_SCAN_TIMEOUT_BREDR_LE);
} else {
hdev->discovery.type = DISCOV_TYPE_LE;
err = hci_le_scan(hdev, LE_SCAN_TYPE,
LE_SCAN_INT, LE_SCAN_WIN,
LE_SCAN_TIMEOUT_LE_ONLY);
}
} else {
hdev->discovery.type = DISCOV_TYPE_BREDR;
err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
}

return err;
}

int mgmt_interleaved_discovery(struct hci_dev *hdev)
{
int err;

BT_DBG("%s", hdev->name);

hci_dev_lock(hdev);

err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE);
if (err < 0)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);

hci_dev_unlock(hdev);

return err;
}

static int start_discovery(struct sock *sk, u16 index,
void *data, u16 len)
{
Expand Down Expand Up @@ -2196,7 +2238,6 @@ static int start_discovery(struct sock *sk, u16 index,

switch (hdev->discovery.type) {
case DISCOV_TYPE_BREDR:
case DISCOV_TYPE_INTERLEAVED:
err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
break;

Expand All @@ -2205,6 +2246,10 @@ static int start_discovery(struct sock *sk, u16 index,
LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
break;

case DISCOV_TYPE_INTERLEAVED:
err = discovery(hdev);
break;

default:
err = -EINVAL;
}
Expand Down

0 comments on commit 5e0452c

Please sign in to comment.