net/bluetooth/hci_sync.c

Source file repositories/reference/linux-study-clean/net/bluetooth/hci_sync.c

File Facts

System
Linux kernel
Corpus path
net/bluetooth/hci_sync.c
Extension
.c
Size
203095 bytes
Lines
7600
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct conn_params {
	bdaddr_t addr;
	u8 addr_type;
	hci_conn_flags_t flags;
	u8 privacy_mode;
};

/* Adds connection to resolve list if needed.
 * Setting params to NULL programs local hdev->irk
 */
static int hci_le_add_resolve_list_sync(struct hci_dev *hdev,
					struct conn_params *params)
{
	struct hci_cp_le_add_to_resolv_list cp;
	struct smp_irk *irk;
	struct bdaddr_list_with_irk *entry;
	struct hci_conn_params *p;

	if (!ll_privacy_capable(hdev))
		return 0;

	/* Attempt to program local identity address, type and irk if params is
	 * NULL.
	 */
	if (!params) {
		if (!hci_dev_test_flag(hdev, HCI_PRIVACY))
			return 0;

		hci_copy_identity_address(hdev, &cp.bdaddr, &cp.bdaddr_type);
		memcpy(cp.peer_irk, hdev->irk, 16);
		goto done;
	} else if (!(params->flags & HCI_CONN_FLAG_ADDRESS_RESOLUTION))
		return 0;

	irk = hci_find_irk_by_addr(hdev, &params->addr, params->addr_type);
	if (!irk)
		return 0;

	/* Check if the IK has _not_ been programmed yet. */
	entry = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list,
						&params->addr,
						params->addr_type);
	if (entry)
		return 0;

	cp.bdaddr_type = params->addr_type;
	bacpy(&cp.bdaddr, &params->addr);
	memcpy(cp.peer_irk, irk->val, 16);

	/* Default privacy mode is always Network */
	params->privacy_mode = HCI_NETWORK_PRIVACY;

	rcu_read_lock();
	p = hci_pend_le_action_lookup(&hdev->pend_le_conns,
				      &params->addr, params->addr_type);
	if (!p)
		p = hci_pend_le_action_lookup(&hdev->pend_le_reports,
					      &params->addr, params->addr_type);
	if (p)
		WRITE_ONCE(p->privacy_mode, HCI_NETWORK_PRIVACY);
	rcu_read_unlock();

done:
	if (hci_dev_test_flag(hdev, HCI_PRIVACY))
		memcpy(cp.local_irk, hdev->irk, 16);
	else
		memset(cp.local_irk, 0, 16);

	return __hci_cmd_sync_status(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST,
				     sizeof(cp), &cp, HCI_CMD_TIMEOUT);
}

/* Set Device Privacy Mode. */
static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
					struct conn_params *params)
{
	struct hci_cp_le_set_privacy_mode cp;
	struct smp_irk *irk;

	if (!ll_privacy_capable(hdev) ||
	    !(params->flags & HCI_CONN_FLAG_ADDRESS_RESOLUTION))
		return 0;

	/* If device privacy mode has already been set there is nothing to do */
	if (params->privacy_mode == HCI_DEVICE_PRIVACY)
		return 0;

	/* Check if HCI_CONN_FLAG_DEVICE_PRIVACY has been set as it also
	 * indicates that LL Privacy has been enabled and
	 * HCI_OP_LE_SET_PRIVACY_MODE is supported.

Annotation

Implementation Notes