Commit 1a942de0 authored by Brian Gix's avatar Brian Gix Committed by Luiz Augusto von Dentz
Browse files

Bluetooth: Move hci_abort_conn to hci_conn.c



hci_abort_conn() is a wrapper around a number of DISCONNECT and
CREATE_CONN_CANCEL commands that was being invoked from hci_request
request queues, which are now deprecated. There are two versions:
hci_abort_conn() which can be invoked from the hci_event thread, and
hci_abort_conn_sync() which can be invoked within a hci_sync cmd chain.

Signed-off-by: default avatarBrian Gix <brian.gix@intel.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 278d933e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2075,6 +2075,7 @@ int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
				  bdaddr_t *bdaddr, u8 addr_type);

int hci_abort_conn(struct hci_conn *conn, u8 reason);
u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
		      u16 to_multiplier);
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
+76 −0
Original line number Diff line number Diff line
@@ -2760,3 +2760,79 @@ u32 hci_conn_get_phy(struct hci_conn *conn)

	return phys;
}

int hci_abort_conn(struct hci_conn *conn, u8 reason)
{
	int r = 0;

	switch (conn->state) {
	case BT_CONNECTED:
	case BT_CONFIG:
		if (conn->type == AMP_LINK) {
			struct hci_cp_disconn_phy_link cp;

			cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
			cp.reason = reason;
			r = hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
					 sizeof(cp), &cp);
		} else {
			struct hci_cp_disconnect dc;

			dc.handle = cpu_to_le16(conn->handle);
			dc.reason = reason;
			r = hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT,
					 sizeof(dc), &dc);
		}

		conn->state = BT_DISCONN;

		break;
	case BT_CONNECT:
		if (conn->type == LE_LINK) {
			if (test_bit(HCI_CONN_SCANNING, &conn->flags))
				break;
			r = hci_send_cmd(conn->hdev,
					 HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
		} else if (conn->type == ACL_LINK) {
			if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2)
				break;
			r = hci_send_cmd(conn->hdev,
					 HCI_OP_CREATE_CONN_CANCEL,
					 6, &conn->dst);
		}
		break;
	case BT_CONNECT2:
		if (conn->type == ACL_LINK) {
			struct hci_cp_reject_conn_req rej;

			bacpy(&rej.bdaddr, &conn->dst);
			rej.reason = reason;

			r = hci_send_cmd(conn->hdev,
					 HCI_OP_REJECT_CONN_REQ,
					 sizeof(rej), &rej);
		} else if (conn->type == SCO_LINK || conn->type == ESCO_LINK) {
			struct hci_cp_reject_sync_conn_req rej;

			bacpy(&rej.bdaddr, &conn->dst);

			/* SCO rejection has its own limited set of
			 * allowed error values (0x0D-0x0F) which isn't
			 * compatible with most values passed to this
			 * function. To be safe hard-code one of the
			 * values that's suitable for SCO.
			 */
			rej.reason = HCI_ERROR_REJ_LIMITED_RESOURCES;

			r = hci_send_cmd(conn->hdev,
					 HCI_OP_REJECT_SYNC_CONN_REQ,
					 sizeof(rej), &rej);
		}
		break;
	default:
		conn->state = BT_CLOSED;
		break;
	}

	return r;
}
+0 −93
Original line number Diff line number Diff line
@@ -909,99 +909,6 @@ static void set_random_addr(struct hci_request *req, bdaddr_t *rpa)
	hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, rpa);
}

static void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn,
			     u8 reason)
{
	switch (conn->state) {
	case BT_CONNECTED:
	case BT_CONFIG:
		if (conn->type == AMP_LINK) {
			struct hci_cp_disconn_phy_link cp;

			cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
			cp.reason = reason;
			hci_req_add(req, HCI_OP_DISCONN_PHY_LINK, sizeof(cp),
				    &cp);
		} else {
			struct hci_cp_disconnect dc;

			dc.handle = cpu_to_le16(conn->handle);
			dc.reason = reason;
			hci_req_add(req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
		}

		conn->state = BT_DISCONN;

		break;
	case BT_CONNECT:
		if (conn->type == LE_LINK) {
			if (test_bit(HCI_CONN_SCANNING, &conn->flags))
				break;
			hci_req_add(req, HCI_OP_LE_CREATE_CONN_CANCEL,
				    0, NULL);
		} else if (conn->type == ACL_LINK) {
			if (req->hdev->hci_ver < BLUETOOTH_VER_1_2)
				break;
			hci_req_add(req, HCI_OP_CREATE_CONN_CANCEL,
				    6, &conn->dst);
		}
		break;
	case BT_CONNECT2:
		if (conn->type == ACL_LINK) {
			struct hci_cp_reject_conn_req rej;

			bacpy(&rej.bdaddr, &conn->dst);
			rej.reason = reason;

			hci_req_add(req, HCI_OP_REJECT_CONN_REQ,
				    sizeof(rej), &rej);
		} else if (conn->type == SCO_LINK || conn->type == ESCO_LINK) {
			struct hci_cp_reject_sync_conn_req rej;

			bacpy(&rej.bdaddr, &conn->dst);

			/* SCO rejection has its own limited set of
			 * allowed error values (0x0D-0x0F) which isn't
			 * compatible with most values passed to this
			 * function. To be safe hard-code one of the
			 * values that's suitable for SCO.
			 */
			rej.reason = HCI_ERROR_REJ_LIMITED_RESOURCES;

			hci_req_add(req, HCI_OP_REJECT_SYNC_CONN_REQ,
				    sizeof(rej), &rej);
		}
		break;
	default:
		conn->state = BT_CLOSED;
		break;
	}
}

static void abort_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{
	if (status)
		bt_dev_dbg(hdev, "Failed to abort connection: status 0x%2.2x", status);
}

int hci_abort_conn(struct hci_conn *conn, u8 reason)
{
	struct hci_request req;
	int err;

	hci_req_init(&req, conn->hdev);

	__hci_abort_conn(&req, conn, reason);

	err = hci_req_run(&req, abort_conn_complete);
	if (err && err != -ENODATA) {
		bt_dev_err(conn->hdev, "failed to run HCI request: err %d", err);
		return err;
	}

	return 0;
}

void hci_request_setup(struct hci_dev *hdev)
{
	INIT_DELAYED_WORK(&hdev->interleave_scan, interleave_scan_work);
+0 −1
Original line number Diff line number Diff line
@@ -73,6 +73,5 @@ void hci_req_add_le_passive_scan(struct hci_request *req);

void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next);

int hci_abort_conn(struct hci_conn *conn, u8 reason);
void hci_request_setup(struct hci_dev *hdev);
void hci_request_cancel_all(struct hci_dev *hdev);
+14 −1
Original line number Diff line number Diff line
@@ -3185,6 +3185,18 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
	return err;
}

static int abort_conn_sync(struct hci_dev *hdev, void *data)
{
	struct hci_conn *conn;
	u16 handle = PTR_ERR(data);

	conn = hci_conn_hash_lookup_handle(hdev, handle);
	if (!conn)
		return 0;

	return hci_abort_conn_sync(hdev, conn, HCI_ERROR_REMOTE_USER_TERM);
}

static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
			      u16 len)
{
@@ -3235,7 +3247,8 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
					      le_addr_type(addr->type));

	if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
		hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
		hci_cmd_sync_queue(hdev, abort_conn_sync, ERR_PTR(conn->handle),
				   NULL);

unlock:
	hci_dev_unlock(hdev);