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