hci_sysfs.c revision e132f7f6a2df7b186563775e79c7ab3612ec8116
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_typetostr(int type) 135{ 136 switch (type) { 137 case HCI_BREDR: 138 return "BR/EDR"; 139 case HCI_AMP: 140 return "AMP"; 141 default: 142 return "UNKNOWN"; 143 } 144} 145 146static ssize_t show_type(struct device *dev, 147 struct device_attribute *attr, char *buf) 148{ 149 struct hci_dev *hdev = to_hci_dev(dev); 150 return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type)); 151} 152 153static ssize_t show_name(struct device *dev, 154 struct device_attribute *attr, char *buf) 155{ 156 struct hci_dev *hdev = to_hci_dev(dev); 157 char name[HCI_MAX_NAME_LENGTH + 1]; 158 int i; 159 160 for (i = 0; i < HCI_MAX_NAME_LENGTH; i++) 161 name[i] = hdev->dev_name[i]; 162 163 name[HCI_MAX_NAME_LENGTH] = '\0'; 164 return sprintf(buf, "%s\n", name); 165} 166 167static ssize_t show_address(struct device *dev, 168 struct device_attribute *attr, char *buf) 169{ 170 struct hci_dev *hdev = to_hci_dev(dev); 171 return sprintf(buf, "%pMR\n", &hdev->bdaddr); 172} 173 174static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); 175static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 176static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); 177 178static struct attribute *bt_host_attrs[] = { 179 &dev_attr_type.attr, 180 &dev_attr_name.attr, 181 &dev_attr_address.attr, 182 NULL 183}; 184 185static struct attribute_group bt_host_group = { 186 .attrs = bt_host_attrs, 187}; 188 189static const struct attribute_group *bt_host_groups[] = { 190 &bt_host_group, 191 NULL 192}; 193 194static void bt_host_release(struct device *dev) 195{ 196 struct hci_dev *hdev = to_hci_dev(dev); 197 kfree(hdev); 198 module_put(THIS_MODULE); 199} 200 201static struct device_type bt_host = { 202 .name = "host", 203 .groups = bt_host_groups, 204 .release = bt_host_release, 205}; 206 207void hci_init_sysfs(struct hci_dev *hdev) 208{ 209 struct device *dev = &hdev->dev; 210 211 dev->type = &bt_host; 212 dev->class = bt_class; 213 214 __module_get(THIS_MODULE); 215 device_initialize(dev); 216} 217 218int __init bt_sysfs_init(void) 219{ 220 bt_class = class_create(THIS_MODULE, "bluetooth"); 221 222 return PTR_ERR_OR_ZERO(bt_class); 223} 224 225void bt_sysfs_cleanup(void) 226{ 227 class_destroy(bt_class); 228} 229