File Index
Files and directories
Sign in
FILE

hci_sysfs.c

File preview with syntax highlighting.

linux-6.19.14/net/bluetooth/hci_sysfs.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Bluetooth HCI driver model support. */
  3
  4#include <linux/module.h>
  5
  6#include <net/bluetooth/bluetooth.h>
  7#include <net/bluetooth/hci_core.h>
  8
  9static const struct class bt_class = {
 10	.name = "bluetooth",
 11};
 12
 13static void bt_link_release(struct device *dev)
 14{
 15	struct hci_conn *conn = to_hci_conn(dev);
 16	kfree(conn);
 17}
 18
 19static const struct device_type bt_link = {
 20	.name    = "link",
 21	.release = bt_link_release,
 22};
 23
 24void hci_conn_init_sysfs(struct hci_conn *conn)
 25{
 26	struct hci_dev *hdev = conn->hdev;
 27
 28	bt_dev_dbg(hdev, "conn %p", conn);
 29
 30	conn->dev.type = &bt_link;
 31	conn->dev.class = &bt_class;
 32	conn->dev.parent = &hdev->dev;
 33
 34	device_initialize(&conn->dev);
 35}
 36
 37void hci_conn_add_sysfs(struct hci_conn *conn)
 38{
 39	struct hci_dev *hdev = conn->hdev;
 40
 41	bt_dev_dbg(hdev, "conn %p", conn);
 42
 43	if (device_is_registered(&conn->dev))
 44		return;
 45
 46	dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
 47
 48	if (device_add(&conn->dev) < 0)
 49		bt_dev_err(hdev, "failed to register connection device");
 50}
 51
 52void hci_conn_del_sysfs(struct hci_conn *conn)
 53{
 54	struct hci_dev *hdev = conn->hdev;
 55
 56	bt_dev_dbg(hdev, "conn %p", conn);
 57
 58	if (!device_is_registered(&conn->dev)) {
 59		/* If device_add() has *not* succeeded, use *only* put_device()
 60		 * to drop the reference count.
 61		 */
 62		put_device(&conn->dev);
 63		return;
 64	}
 65
 66	/* If there are devices using the connection as parent reset it to NULL
 67	 * before unregistering the device.
 68	 */
 69	while (1) {
 70		struct device *dev;
 71
 72		dev = device_find_any_child(&conn->dev);
 73		if (!dev)
 74			break;
 75		device_move(dev, NULL, DPM_ORDER_DEV_LAST);
 76		put_device(dev);
 77	}
 78
 79	device_unregister(&conn->dev);
 80}
 81
 82static void bt_host_release(struct device *dev)
 83{
 84	struct hci_dev *hdev = to_hci_dev(dev);
 85
 86	if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
 87		hci_release_dev(hdev);
 88	else
 89		kfree(hdev);
 90	module_put(THIS_MODULE);
 91}
 92
 93static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
 94			   const char *buf, size_t count)
 95{
 96	struct hci_dev *hdev = to_hci_dev(dev);
 97
 98	if (hdev->reset)
 99		hdev->reset(hdev);
100
101	return count;
102}
103static DEVICE_ATTR_WO(reset);
104
105static struct attribute *bt_host_attrs[] = {
106	&dev_attr_reset.attr,
107	NULL,
108};
109ATTRIBUTE_GROUPS(bt_host);
110
111static const struct device_type bt_host = {
112	.name    = "host",
113	.release = bt_host_release,
114	.groups = bt_host_groups,
115};
116
117void hci_init_sysfs(struct hci_dev *hdev)
118{
119	struct device *dev = &hdev->dev;
120
121	dev->type = &bt_host;
122	dev->class = &bt_class;
123
124	__module_get(THIS_MODULE);
125	device_initialize(dev);
126}
127
128int __init bt_sysfs_init(void)
129{
130	return class_register(&bt_class);
131}
132
133void bt_sysfs_cleanup(void)
134{
135	class_unregister(&bt_class);
136}
~/ Read-only file preview.