xref: /openbmc/linux/net/bluetooth/hci_sysfs.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1 /* Bluetooth HCI driver model support. */
2 
3 #include <linux/config.h>
4 #include <linux/kernel.h>
5 #include <linux/init.h>
6 
7 #include <net/bluetooth/bluetooth.h>
8 #include <net/bluetooth/hci_core.h>
9 
10 #ifndef CONFIG_BT_HCI_CORE_DEBUG
11 #undef  BT_DBG
12 #define BT_DBG(D...)
13 #endif
14 
15 static ssize_t show_name(struct class_device *cdev, char *buf)
16 {
17 	struct hci_dev *hdev = class_get_devdata(cdev);
18 	return sprintf(buf, "%s\n", hdev->name);
19 }
20 
21 static ssize_t show_type(struct class_device *cdev, char *buf)
22 {
23 	struct hci_dev *hdev = class_get_devdata(cdev);
24 	return sprintf(buf, "%d\n", hdev->type);
25 }
26 
27 static ssize_t show_address(struct class_device *cdev, char *buf)
28 {
29 	struct hci_dev *hdev = class_get_devdata(cdev);
30 	bdaddr_t bdaddr;
31 	baswap(&bdaddr, &hdev->bdaddr);
32 	return sprintf(buf, "%s\n", batostr(&bdaddr));
33 }
34 
35 static ssize_t show_flags(struct class_device *cdev, char *buf)
36 {
37 	struct hci_dev *hdev = class_get_devdata(cdev);
38 	return sprintf(buf, "0x%lx\n", hdev->flags);
39 }
40 
41 static ssize_t show_inquiry_cache(struct class_device *cdev, char *buf)
42 {
43 	struct hci_dev *hdev = class_get_devdata(cdev);
44 	struct inquiry_cache *cache = &hdev->inq_cache;
45 	struct inquiry_entry *e;
46 	int n = 0;
47 
48 	hci_dev_lock_bh(hdev);
49 
50 	for (e = cache->list; e; e = e->next) {
51 		struct inquiry_data *data = &e->data;
52 		bdaddr_t bdaddr;
53 		baswap(&bdaddr, &data->bdaddr);
54 		n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %u\n",
55 				batostr(&bdaddr),
56 				data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode,
57 				data->dev_class[2], data->dev_class[1], data->dev_class[0],
58 				__le16_to_cpu(data->clock_offset), data->rssi, e->timestamp);
59 	}
60 
61 	hci_dev_unlock_bh(hdev);
62 	return n;
63 }
64 
65 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
66 static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
67 static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
68 static CLASS_DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
69 static CLASS_DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
70 
71 static struct class_device_attribute *bt_attrs[] = {
72 	&class_device_attr_name,
73 	&class_device_attr_type,
74 	&class_device_attr_address,
75 	&class_device_attr_flags,
76 	&class_device_attr_inquiry_cache,
77 	NULL
78 };
79 
80 #ifdef CONFIG_HOTPLUG
81 static int bt_hotplug(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
82 {
83 	struct hci_dev *hdev = class_get_devdata(cdev);
84 	int n, i = 0;
85 
86 	envp[i++] = buf;
87 	n = snprintf(buf, size, "INTERFACE=%s", hdev->name) + 1;
88 	buf += n;
89 	size -= n;
90 
91 	if ((size <= 0) || (i >= num_envp))
92 		return -ENOMEM;
93 
94 	envp[i] = NULL;
95 	return 0;
96 }
97 #endif
98 
99 static void bt_release(struct class_device *cdev)
100 {
101 	struct hci_dev *hdev = class_get_devdata(cdev);
102 
103 	kfree(hdev);
104 }
105 
106 static struct class bt_class = {
107 	.name		= "bluetooth",
108 	.release	= bt_release,
109 #ifdef CONFIG_HOTPLUG
110 	.hotplug	= bt_hotplug,
111 #endif
112 };
113 
114 int hci_register_sysfs(struct hci_dev *hdev)
115 {
116 	struct class_device *cdev = &hdev->class_dev;
117 	unsigned int i;
118 	int err;
119 
120 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
121 
122 	cdev->class = &bt_class;
123 	class_set_devdata(cdev, hdev);
124 
125 	strlcpy(cdev->class_id, hdev->name, BUS_ID_SIZE);
126 	err = class_device_register(cdev);
127 	if (err < 0)
128 		return err;
129 
130 	for (i = 0; bt_attrs[i]; i++)
131 		class_device_create_file(cdev, bt_attrs[i]);
132 
133 	return 0;
134 }
135 
136 void hci_unregister_sysfs(struct hci_dev *hdev)
137 {
138 	struct class_device * cdev = &hdev->class_dev;
139 
140 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
141 
142 	class_device_del(cdev);
143 }
144 
145 int __init bt_sysfs_init(void)
146 {
147 	return class_register(&bt_class);
148 }
149 
150 void __exit bt_sysfs_cleanup(void)
151 {
152 	class_unregister(&bt_class);
153 }
154