Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/bluetooth/hci_sysfs.c
26282 views
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
9
static const struct class bt_class = {
10
.name = "bluetooth",
11
};
12
13
static void bt_link_release(struct device *dev)
14
{
15
struct hci_conn *conn = to_hci_conn(dev);
16
kfree(conn);
17
}
18
19
static const struct device_type bt_link = {
20
.name = "link",
21
.release = bt_link_release,
22
};
23
24
void 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
37
void 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
52
void 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
82
static 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
93
static 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
}
103
static DEVICE_ATTR_WO(reset);
104
105
static struct attribute *bt_host_attrs[] = {
106
&dev_attr_reset.attr,
107
NULL,
108
};
109
ATTRIBUTE_GROUPS(bt_host);
110
111
static const struct device_type bt_host = {
112
.name = "host",
113
.release = bt_host_release,
114
.groups = bt_host_groups,
115
};
116
117
void 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
128
int __init bt_sysfs_init(void)
129
{
130
return class_register(&bt_class);
131
}
132
133
void bt_sysfs_cleanup(void)
134
{
135
class_unregister(&bt_class);
136
}
137
138