blob: 555982a78a585513431722a7f65e1934dc081f86 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* Bluetooth HCI driver model support. */
2
Paul Gortmaker3a9a2312011-05-27 09:12:25 -04003#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5#include <net/bluetooth/bluetooth.h>
6#include <net/bluetooth/hci_core.h>
7
Marcel Holtmannaef7d972010-03-21 05:27:45 +01008static struct class *bt_class;
Marcel Holtmann90855d72008-08-18 13:23:53 +02009
Marcel Holtmann90855d72008-08-18 13:23:53 +020010static 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";
Peter Hurley21061df2011-08-24 10:04:56 -040019 case LE_LINK:
20 return "LE";
Marcel Holtmann90855d72008-08-18 13:23:53 +020021 default:
22 return "UNKNOWN";
23 }
24}
25
Gustavo Padovanb80f0212012-05-17 00:36:23 -030026static ssize_t show_link_type(struct device *dev,
27 struct device_attribute *attr, char *buf)
Marcel Holtmann90855d72008-08-18 13:23:53 +020028{
David Herrmann3dc07322012-02-09 21:58:33 +010029 struct hci_conn *conn = to_hci_conn(dev);
Marcel Holtmann90855d72008-08-18 13:23:53 +020030 return sprintf(buf, "%s\n", link_typetostr(conn->type));
31}
32
Gustavo Padovanb80f0212012-05-17 00:36:23 -030033static ssize_t show_link_address(struct device *dev,
34 struct device_attribute *attr, char *buf)
Marcel Holtmann90855d72008-08-18 13:23:53 +020035{
David Herrmann3dc07322012-02-09 21:58:33 +010036 struct hci_conn *conn = to_hci_conn(dev);
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +030037 return sprintf(buf, "%pMR\n", &conn->dst);
Marcel Holtmann90855d72008-08-18 13:23:53 +020038}
39
Gustavo F. Padovan602f9882011-02-17 19:22:19 -030040#define LINK_ATTR(_name, _mode, _show, _store) \
41struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store)
Marcel Holtmann90855d72008-08-18 13:23:53 +020042
43static LINK_ATTR(type, S_IRUGO, show_link_type, NULL);
44static LINK_ATTR(address, S_IRUGO, show_link_address, NULL);
Marcel Holtmann90855d72008-08-18 13:23:53 +020045
46static struct attribute *bt_link_attrs[] = {
47 &link_attr_type.attr,
48 &link_attr_address.attr,
Marcel Holtmann90855d72008-08-18 13:23:53 +020049 NULL
50};
51
Wei Yongjunb8480792014-01-07 22:23:08 +080052ATTRIBUTE_GROUPS(bt_link);
Marcel Holtmann90855d72008-08-18 13:23:53 +020053
54static void bt_link_release(struct device *dev)
55{
David Herrmann2dd10682012-02-09 21:58:34 +010056 struct hci_conn *conn = to_hci_conn(dev);
57 kfree(conn);
Marcel Holtmann90855d72008-08-18 13:23:53 +020058}
59
60static struct device_type bt_link = {
61 .name = "link",
62 .groups = bt_link_groups,
63 .release = bt_link_release,
64};
65
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -020066/*
67 * The rfcomm tty device will possibly retain even when conn
68 * is down, and sysfs doesn't support move zombie device,
69 * so we should move the device before conn device is destroyed.
70 */
71static int __match_tty(struct device *dev, void *data)
Marcel Holtmann90855d72008-08-18 13:23:53 +020072{
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -020073 return !strncmp(dev_name(dev), "rfcomm", 6);
74}
75
76void hci_conn_init_sysfs(struct hci_conn *conn)
77{
Marcel Holtmann457ca7b2009-05-05 13:09:01 -070078 struct hci_dev *hdev = conn->hdev;
Marcel Holtmann90855d72008-08-18 13:23:53 +020079
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -020080 BT_DBG("conn %p", conn);
81
82 conn->dev.type = &bt_link;
83 conn->dev.class = bt_class;
84 conn->dev.parent = &hdev->dev;
85
86 device_initialize(&conn->dev);
87}
88
89void hci_conn_add_sysfs(struct hci_conn *conn)
90{
91 struct hci_dev *hdev = conn->hdev;
92
93 BT_DBG("conn %p", conn);
94
Marcel Holtmann457ca7b2009-05-05 13:09:01 -070095 dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
96
Marcel Holtmann90855d72008-08-18 13:23:53 +020097 if (device_add(&conn->dev) < 0) {
98 BT_ERR("Failed to register connection device");
99 return;
100 }
Marcel Holtmann384943e2009-05-08 18:20:43 -0700101
102 hci_dev_hold(hdev);
Marcel Holtmann90855d72008-08-18 13:23:53 +0200103}
104
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -0200105void hci_conn_del_sysfs(struct hci_conn *conn)
Marcel Holtmann90855d72008-08-18 13:23:53 +0200106{
Marcel Holtmann90855d72008-08-18 13:23:53 +0200107 struct hci_dev *hdev = conn->hdev;
108
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700109 if (!device_is_registered(&conn->dev))
110 return;
Roger Quadrosf3784d82009-04-23 14:50:54 +0300111
Marcel Holtmann90855d72008-08-18 13:23:53 +0200112 while (1) {
113 struct device *dev;
114
115 dev = device_find_child(&conn->dev, NULL, __match_tty);
116 if (!dev)
117 break;
Cornelia Huckffa6a702009-03-04 12:44:00 +0100118 device_move(dev, NULL, DPM_ORDER_DEV_LAST);
Marcel Holtmann90855d72008-08-18 13:23:53 +0200119 put_device(dev);
120 }
121
122 device_del(&conn->dev);
Marcel Holtmann384943e2009-05-08 18:20:43 -0700123
Marcel Holtmann90855d72008-08-18 13:23:53 +0200124 hci_dev_put(hdev);
125}
126
Marcel Holtmann943da252010-02-13 02:28:41 +0100127static inline char *host_typetostr(int type)
128{
129 switch (type) {
130 case HCI_BREDR:
131 return "BR/EDR";
David Vrabel8f1e1742010-08-09 17:38:10 -0400132 case HCI_AMP:
133 return "AMP";
Marcel Holtmann943da252010-02-13 02:28:41 +0100134 default:
135 return "UNKNOWN";
136 }
137}
138
Gustavo Padovanb80f0212012-05-17 00:36:23 -0300139static ssize_t show_type(struct device *dev,
140 struct device_attribute *attr, char *buf)
Marcel Holtmann943da252010-02-13 02:28:41 +0100141{
David Herrmannaa2b86d2012-02-09 21:58:30 +0100142 struct hci_dev *hdev = to_hci_dev(dev);
Marcel Holtmann943da252010-02-13 02:28:41 +0100143 return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type));
144}
145
Gustavo Padovanb80f0212012-05-17 00:36:23 -0300146static ssize_t show_name(struct device *dev,
147 struct device_attribute *attr, char *buf)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200148{
David Herrmannaa2b86d2012-02-09 21:58:30 +0100149 struct hci_dev *hdev = to_hci_dev(dev);
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200150 char name[HCI_MAX_NAME_LENGTH + 1];
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200151 int i;
152
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200153 for (i = 0; i < HCI_MAX_NAME_LENGTH; i++)
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200154 name[i] = hdev->dev_name[i];
155
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200156 name[HCI_MAX_NAME_LENGTH] = '\0';
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200157 return sprintf(buf, "%s\n", name);
158}
159
Gustavo Padovanb80f0212012-05-17 00:36:23 -0300160static ssize_t show_address(struct device *dev,
161 struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
David Herrmannaa2b86d2012-02-09 21:58:30 +0100163 struct hci_dev *hdev = to_hci_dev(dev);
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +0300164 return sprintf(buf, "%pMR\n", &hdev->bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165}
166
Marcel Holtmann943da252010-02-13 02:28:41 +0100167static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200168static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200169static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
Marcel Holtmann90855d72008-08-18 13:23:53 +0200171static struct attribute *bt_host_attrs[] = {
Marcel Holtmann943da252010-02-13 02:28:41 +0100172 &dev_attr_type.attr,
Marcel Holtmann90855d72008-08-18 13:23:53 +0200173 &dev_attr_name.attr,
Marcel Holtmann90855d72008-08-18 13:23:53 +0200174 &dev_attr_address.attr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 NULL
176};
177
Wei Yongjunb8480792014-01-07 22:23:08 +0800178ATTRIBUTE_GROUPS(bt_host);
Marcel Holtmannb219e3a2006-07-06 12:38:46 +0200179
Marcel Holtmann90855d72008-08-18 13:23:53 +0200180static void bt_host_release(struct device *dev)
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200181{
David Herrmann2dd10682012-02-09 21:58:34 +0100182 struct hci_dev *hdev = to_hci_dev(dev);
183 kfree(hdev);
David Herrmann46e06532012-01-07 15:47:21 +0100184 module_put(THIS_MODULE);
Marcel Holtmannb219e3a2006-07-06 12:38:46 +0200185}
186
Marcel Holtmann90855d72008-08-18 13:23:53 +0200187static struct device_type bt_host = {
188 .name = "host",
189 .groups = bt_host_groups,
190 .release = bt_host_release,
191};
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200192
David Herrmann0ac7e702011-10-08 14:58:47 +0200193void hci_init_sysfs(struct hci_dev *hdev)
194{
195 struct device *dev = &hdev->dev;
196
197 dev->type = &bt_host;
198 dev->class = bt_class;
199
David Herrmann46e06532012-01-07 15:47:21 +0100200 __module_get(THIS_MODULE);
David Herrmann0ac7e702011-10-08 14:58:47 +0200201 device_initialize(dev);
202}
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204int __init bt_sysfs_init(void)
205{
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200206 bt_class = class_create(THIS_MODULE, "bluetooth");
Marcel Holtmann27d35282006-07-03 10:02:37 +0200207
Rusty Russell8c6ffba2013-07-15 11:20:32 +0930208 return PTR_ERR_OR_ZERO(bt_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209}
210
Arnaud Patard860e13b2006-09-28 15:29:37 -0700211void bt_sysfs_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212{
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200213 class_destroy(bt_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214}