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