Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff9ef578 authored by Johan Hedberg's avatar Johan Hedberg
Browse files

Bluetooth: Add discovery state tracking



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: default avatarJohan Hedberg <johan.hedberg@intel.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 30883512
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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);
+25 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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)
+3 −3
Original line number Diff line number Diff line
@@ -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);
@@ -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);
}

@@ -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);
}

+16 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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;
@@ -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);