hci_sysfs.c revision f96bc0a7f4ceee53ee3ef3a2983c81f84c5d6a89
1/* Bluetooth HCI driver model support. */
2
3#include <linux/module.h>
4
5#include <net/bluetooth/bluetooth.h>
6#include <net/bluetooth/hci_core.h>
7
8static struct class *bt_class;
9
10static inline char *link_typetostr(int type)
11{
12	switch (type) {
13	case ACL_LINK:
14		return "ACL";
15	case SCO_LINK:
16		return "SCO";
17	case ESCO_LINK:
18		return "eSCO";
19	case LE_LINK:
20		return "LE";
21	default:
22		return "UNKNOWN";
23	}
24}
25
26static ssize_t show_link_type(struct device *dev,
27			      struct device_attribute *attr, char *buf)
28{
29	struct hci_conn *conn = to_hci_conn(dev);
30	return sprintf(buf, "%s\n", link_typetostr(conn->type));
31}
32
33static ssize_t show_link_address(struct device *dev,
34				 struct device_attribute *attr, char *buf)
35{
36	struct hci_conn *conn = to_hci_conn(dev);
37	return sprintf(buf, "%pMR\n", &conn->dst);
38}
39
40#define LINK_ATTR(_name, _mode, _show, _store) \
41struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store)
42
43static LINK_ATTR(type, S_IRUGO, show_link_type, NULL);
44static LINK_ATTR(address, S_IRUGO, show_link_address, NULL);
45
46static struct attribute *bt_link_attrs[] = {
47	&link_attr_type.attr,
48	&link_attr_address.attr,
49	NULL
50};
51
52static struct attribute_group bt_link_group = {
53	.attrs = bt_link_attrs,
54};
55
56static const struct attribute_group *bt_link_groups[] = {
57	&bt_link_group,
58	NULL
59};
60
61static void bt_link_release(struct device *dev)
62{
63	struct hci_conn *conn = to_hci_conn(dev);
64	kfree(conn);
65}
66
67static struct device_type bt_link = {
68	.name    = "link",
69	.groups  = bt_link_groups,
70	.release = bt_link_release,
71};
72
73/*
74 * The rfcomm tty device will possibly retain even when conn
75 * is down, and sysfs doesn't support move zombie device,
76 * so we should move the device before conn device is destroyed.
77 */
78static int __match_tty(struct device *dev, void *data)
79{
80	return !strncmp(dev_name(dev), "rfcomm", 6);
81}
82
83void hci_conn_init_sysfs(struct hci_conn *conn)
84{
85	struct hci_dev *hdev = conn->hdev;
86
87	BT_DBG("conn %p", conn);
88
89	conn->dev.type = &bt_link;
90	conn->dev.class = bt_class;
91	conn->dev.parent = &hdev->dev;
92
93	device_initialize(&conn->dev);
94}
95
96void hci_conn_add_sysfs(struct hci_conn *conn)
97{
98	struct hci_dev *hdev = conn->hdev;
99
100	BT_DBG("conn %p", conn);
101
102	dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
103
104	if (device_add(&conn->dev) < 0) {
105		BT_ERR("Failed to register connection device");
106		return;
107	}
108
109	hci_dev_hold(hdev);
110}
111
112void hci_conn_del_sysfs(struct hci_conn *conn)
113{
114	struct hci_dev *hdev = conn->hdev;
115
116	if (!device_is_registered(&conn->dev))
117		return;
118
119	while (1) {
120		struct device *dev;
121
122		dev = device_find_child(&conn->dev, NULL, __match_tty);
123		if (!dev)
124			break;
125		device_move(dev, NULL, DPM_ORDER_DEV_LAST);
126		put_device(dev);
127	}
128
129	device_del(&conn->dev);
130
131	hci_dev_put(hdev);
132}
133
134static inline char *host_bustostr(int bus)
135{
136	switch (bus) {
137	case HCI_VIRTUAL:
138		return "VIRTUAL";
139	case HCI_USB:
140		return "USB";
141	case HCI_PCCARD:
142		return "PCCARD";
143	case HCI_UART:
144		return "UART";
145	case HCI_RS232:
146		return "RS232";
147	case HCI_PCI:
148		return "PCI";
149	case HCI_SDIO:
150		return "SDIO";
151	default:
152		return "UNKNOWN";
153	}
154}
155
156static inline char *host_typetostr(int type)
157{
158	switch (type) {
159	case HCI_BREDR:
160		return "BR/EDR";
161	case HCI_AMP:
162		return "AMP";
163	default:
164		return "UNKNOWN";
165	}
166}
167
168static ssize_t show_bus(struct device *dev,
169			struct device_attribute *attr, char *buf)
170{
171	struct hci_dev *hdev = to_hci_dev(dev);
172	return sprintf(buf, "%s\n", host_bustostr(hdev->bus));
173}
174
175static ssize_t show_type(struct device *dev,
176			 struct device_attribute *attr, char *buf)
177{
178	struct hci_dev *hdev = to_hci_dev(dev);
179	return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type));
180}
181
182static ssize_t show_name(struct device *dev,
183			 struct device_attribute *attr, char *buf)
184{
185	struct hci_dev *hdev = to_hci_dev(dev);
186	char name[HCI_MAX_NAME_LENGTH + 1];
187	int i;
188
189	for (i = 0; i < HCI_MAX_NAME_LENGTH; i++)
190		name[i] = hdev->dev_name[i];
191
192	name[HCI_MAX_NAME_LENGTH] = '\0';
193	return sprintf(buf, "%s\n", name);
194}
195
196static ssize_t show_class(struct device *dev,
197			  struct device_attribute *attr, char *buf)
198{
199	struct hci_dev *hdev = to_hci_dev(dev);
200	return sprintf(buf, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
201		       hdev->dev_class[1], hdev->dev_class[0]);
202}
203
204static ssize_t show_address(struct device *dev,
205			    struct device_attribute *attr, char *buf)
206{
207	struct hci_dev *hdev = to_hci_dev(dev);
208	return sprintf(buf, "%pMR\n", &hdev->bdaddr);
209}
210
211static ssize_t show_manufacturer(struct device *dev,
212				 struct device_attribute *attr, char *buf)
213{
214	struct hci_dev *hdev = to_hci_dev(dev);
215	return sprintf(buf, "%d\n", hdev->manufacturer);
216}
217
218static ssize_t show_hci_version(struct device *dev,
219				struct device_attribute *attr, char *buf)
220{
221	struct hci_dev *hdev = to_hci_dev(dev);
222	return sprintf(buf, "%d\n", hdev->hci_ver);
223}
224
225static ssize_t show_hci_revision(struct device *dev,
226				 struct device_attribute *attr, char *buf)
227{
228	struct hci_dev *hdev = to_hci_dev(dev);
229	return sprintf(buf, "%d\n", hdev->hci_rev);
230}
231
232static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL);
233static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
234static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
235static DEVICE_ATTR(class, S_IRUGO, show_class, NULL);
236static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
237static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
238static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
239static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
240
241static struct attribute *bt_host_attrs[] = {
242	&dev_attr_bus.attr,
243	&dev_attr_type.attr,
244	&dev_attr_name.attr,
245	&dev_attr_class.attr,
246	&dev_attr_address.attr,
247	&dev_attr_manufacturer.attr,
248	&dev_attr_hci_version.attr,
249	&dev_attr_hci_revision.attr,
250	NULL
251};
252
253static struct attribute_group bt_host_group = {
254	.attrs = bt_host_attrs,
255};
256
257static const struct attribute_group *bt_host_groups[] = {
258	&bt_host_group,
259	NULL
260};
261
262static void bt_host_release(struct device *dev)
263{
264	struct hci_dev *hdev = to_hci_dev(dev);
265	kfree(hdev);
266	module_put(THIS_MODULE);
267}
268
269static struct device_type bt_host = {
270	.name    = "host",
271	.groups  = bt_host_groups,
272	.release = bt_host_release,
273};
274
275void hci_init_sysfs(struct hci_dev *hdev)
276{
277	struct device *dev = &hdev->dev;
278
279	dev->type = &bt_host;
280	dev->class = bt_class;
281
282	__module_get(THIS_MODULE);
283	device_initialize(dev);
284}
285
286int __init bt_sysfs_init(void)
287{
288	bt_class = class_create(THIS_MODULE, "bluetooth");
289
290	return PTR_ERR_OR_ZERO(bt_class);
291}
292
293void bt_sysfs_cleanup(void)
294{
295	class_destroy(bt_class);
296}
297