net/bluetooth/hci_core.c

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

File Facts

System
Linux kernel
Corpus path
net/bluetooth/hci_core.c
Extension
.c
Size
96809 bytes
Lines
4129
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

error = device_add(&hdev->dev);
	if (error < 0)
		goto err_wqueue;

	hci_leds_init(hdev);

	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
				    RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops,
				    hdev);
	if (hdev->rfkill) {
		if (rfkill_register(hdev->rfkill) < 0) {
			rfkill_destroy(hdev->rfkill);
			hdev->rfkill = NULL;
		}
	}

	if (hdev->rfkill && rfkill_blocked(hdev->rfkill))
		hci_dev_set_flag(hdev, HCI_RFKILLED);

	hci_dev_set_flag(hdev, HCI_SETUP);
	hci_dev_set_flag(hdev, HCI_AUTO_OFF);

	/* Assume BR/EDR support until proven otherwise (such as
	 * through reading supported features during init.
	 */
	hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);

	write_lock(&hci_dev_list_lock);
	list_add(&hdev->list, &hci_dev_list);
	write_unlock(&hci_dev_list_lock);

	/* Devices that are marked for raw-only usage are unconfigured
	 * and should not be included in normal operation.
	 */
	if (hci_test_quirk(hdev, HCI_QUIRK_RAW_DEVICE))
		hci_dev_set_flag(hdev, HCI_UNCONFIGURED);

	/* Mark Remote Wakeup connection flag as supported if driver has wakeup
	 * callback.
	 */
	if (hdev->wakeup)
		hdev->conn_flags |= HCI_CONN_FLAG_REMOTE_WAKEUP;

	hci_sock_dev_event(hdev, HCI_DEV_REG);
	hci_dev_hold(hdev);

	error = hci_register_suspend_notifier(hdev);
	if (error)
		BT_WARN("register suspend notifier failed error:%d\n", error);

	queue_work(hdev->req_workqueue, &hdev->power_on);

	idr_init(&hdev->adv_monitors_idr);
	msft_register(hdev);

	return id;

err_wqueue:
	debugfs_remove_recursive(hdev->debugfs);
	destroy_workqueue(hdev->workqueue);
	destroy_workqueue(hdev->req_workqueue);
err:
	ida_free(&hci_index_ida, hdev->id);

	return error;
}
EXPORT_SYMBOL(hci_register_dev);

/* Unregister HCI device */
void hci_unregister_dev(struct hci_dev *hdev)
{
	BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);

	mutex_lock(&hdev->unregister_lock);
	hci_dev_set_flag(hdev, HCI_UNREGISTER);
	mutex_unlock(&hdev->unregister_lock);

	write_lock(&hci_dev_list_lock);
	list_del(&hdev->list);
	write_unlock(&hci_dev_list_lock);

	synchronize_srcu(&hdev->srcu);
	cleanup_srcu_struct(&hdev->srcu);

	disable_work_sync(&hdev->rx_work);
	disable_work_sync(&hdev->cmd_work);
	disable_work_sync(&hdev->tx_work);
	disable_work_sync(&hdev->power_on);
	disable_work_sync(&hdev->error_reset);
	disable_delayed_work_sync(&hdev->cmd_timer);

Annotation

Implementation Notes