Skip to content

Commit

Permalink
Bluetooth: Add discovery state tracking
Browse files Browse the repository at this point in the history
This patch adds proper state tracking to the device discovery process.
This makes it possible to return appropriate errors when trying to stop
a non-active discovery or start discovery when it is already ongoing.
Once name resolving is implemented this also makes it possible to know
what the right action to do is when a remote name lookup is cancelled.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Johan Hedberg committed Feb 13, 2012
1 parent 3088351 commit ff9ef57
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 3 deletions.
9 changes: 9 additions & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ struct inquiry_entry {
};

struct discovery_state {
enum {
DISCOVERY_STOPPED,
DISCOVERY_STARTING,
DISCOVERY_ACTIVE,
DISCOVERY_STOPPING,
} state;
struct list_head all; /* All devices found during inquiry */
struct list_head unknown; /* Name state not known */
struct list_head resolve; /* Name needs to be resolved */
Expand Down Expand Up @@ -359,11 +365,14 @@ extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);

static inline void discovery_init(struct hci_dev *hdev)
{
hdev->discovery.state = DISCOVERY_STOPPED;
INIT_LIST_HEAD(&hdev->discovery.all);
INIT_LIST_HEAD(&hdev->discovery.unknown);
INIT_LIST_HEAD(&hdev->discovery.resolve);
}

void hci_discovery_set_state(struct hci_dev *hdev, int state);

static inline int inquiry_cache_empty(struct hci_dev *hdev)
{
return list_empty(&hdev->discovery.all);
Expand Down
25 changes: 25 additions & 0 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,30 @@ struct hci_dev *hci_dev_get(int index)
}

/* ---- Inquiry support ---- */

void hci_discovery_set_state(struct hci_dev *hdev, int state)
{
BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state);

if (hdev->discovery.state == state)
return;

switch (state) {
case DISCOVERY_STOPPED:
mgmt_discovering(hdev, 0);
break;
case DISCOVERY_STARTING:
break;
case DISCOVERY_ACTIVE:
mgmt_discovering(hdev, 1);
break;
case DISCOVERY_STOPPING:
break;
}

hdev->discovery.state = state;
}

static void inquiry_cache_flush(struct hci_dev *hdev)
{
struct discovery_state *cache = &hdev->discovery;
Expand All @@ -367,6 +391,7 @@ static void inquiry_cache_flush(struct hci_dev *hdev)

INIT_LIST_HEAD(&cache->unknown);
INIT_LIST_HEAD(&cache->resolve);
cache->state = DISCOVERY_STOPPED;
}

struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
Expand Down
6 changes: 3 additions & 3 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit(HCI_INQUIRY, &hdev->flags);

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

hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
Expand Down Expand Up @@ -1119,7 +1119,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
set_bit(HCI_INQUIRY, &hdev->flags);

hci_dev_lock(hdev);
mgmt_discovering(hdev, 1);
hci_discovery_set_state(hdev, DISCOVERY_ACTIVE);
hci_dev_unlock(hdev);
}

Expand Down Expand Up @@ -1507,7 +1507,7 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
return;

hci_dev_lock(hdev);
mgmt_discovering(hdev, 0);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);
}

Expand Down
16 changes: 16 additions & 0 deletions net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,12 @@ static int start_discovery(struct sock *sk, u16 index,
goto failed;
}

if (hdev->discovery.state != DISCOVERY_STOPPED) {
err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY);
goto failed;
}

cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
if (!cmd) {
err = -ENOMEM;
Expand All @@ -1927,6 +1933,8 @@ static int start_discovery(struct sock *sk, u16 index,
err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
if (err < 0)
mgmt_pending_remove(cmd);
else
hci_discovery_set_state(hdev, DISCOVERY_STARTING);

failed:
hci_dev_unlock(hdev);
Expand All @@ -1950,6 +1958,12 @@ static int stop_discovery(struct sock *sk, u16 index)

hci_dev_lock(hdev);

if (hdev->discovery.state != DISCOVERY_ACTIVE) {
err = cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
MGMT_STATUS_REJECTED);
goto failed;
}

cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
if (!cmd) {
err = -ENOMEM;
Expand All @@ -1959,6 +1973,8 @@ static int stop_discovery(struct sock *sk, u16 index)
err = hci_cancel_inquiry(hdev);
if (err < 0)
mgmt_pending_remove(cmd);
else
hci_discovery_set_state(hdev, DISCOVERY_STOPPING);

failed:
hci_dev_unlock(hdev);
Expand Down

0 comments on commit ff9ef57

Please sign in to comment.