1 // SPDX-License-Identifier: GPL-2.0 2 /* Bluetooth HCI driver model support. */ 3 4 #include <linux/module.h> 5 6 #include <net/bluetooth/bluetooth.h> 7 #include <net/bluetooth/hci_core.h> 8 9 static struct class *bt_class; 10 11 static void bt_link_release(struct device *dev) 12 { 13 struct hci_conn *conn = to_hci_conn(dev); 14 kfree(conn); 15 } 16 17 static const struct device_type bt_link = { 18 .name = "link", 19 .release = bt_link_release, 20 }; 21 22 /* 23 * The rfcomm tty device will possibly retain even when conn 24 * is down, and sysfs doesn't support move zombie device, 25 * so we should move the device before conn device is destroyed. 26 */ 27 static int __match_tty(struct device *dev, void *data) 28 { 29 return !strncmp(dev_name(dev), "rfcomm", 6); 30 } 31 32 void hci_conn_init_sysfs(struct hci_conn *conn) 33 { 34 struct hci_dev *hdev = conn->hdev; 35 36 BT_DBG("conn %p", conn); 37 38 conn->dev.type = &bt_link; 39 conn->dev.class = bt_class; 40 conn->dev.parent = &hdev->dev; 41 42 device_initialize(&conn->dev); 43 } 44 45 void hci_conn_add_sysfs(struct hci_conn *conn) 46 { 47 struct hci_dev *hdev = conn->hdev; 48 49 BT_DBG("conn %p", conn); 50 51 dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); 52 53 if (device_add(&conn->dev) < 0) { 54 bt_dev_err(hdev, "failed to register connection device"); 55 return; 56 } 57 58 hci_dev_hold(hdev); 59 } 60 61 void hci_conn_del_sysfs(struct hci_conn *conn) 62 { 63 struct hci_dev *hdev = conn->hdev; 64 65 if (!device_is_registered(&conn->dev)) 66 return; 67 68 while (1) { 69 struct device *dev; 70 71 dev = device_find_child(&conn->dev, NULL, __match_tty); 72 if (!dev) 73 break; 74 device_move(dev, NULL, DPM_ORDER_DEV_LAST); 75 put_device(dev); 76 } 77 78 device_del(&conn->dev); 79 80 hci_dev_put(hdev); 81 } 82 83 static void bt_host_release(struct device *dev) 84 { 85 struct hci_dev *hdev = to_hci_dev(dev); 86 87 if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) 88 hci_release_dev(hdev); 89 module_put(THIS_MODULE); 90 } 91 92 static const struct device_type bt_host = { 93 .name = "host", 94 .release = bt_host_release, 95 }; 96 97 void hci_init_sysfs(struct hci_dev *hdev) 98 { 99 struct device *dev = &hdev->dev; 100 101 dev->type = &bt_host; 102 dev->class = bt_class; 103 104 __module_get(THIS_MODULE); 105 device_initialize(dev); 106 } 107 108 int __init bt_sysfs_init(void) 109 { 110 bt_class = class_create(THIS_MODULE, "bluetooth"); 111 112 return PTR_ERR_OR_ZERO(bt_class); 113 } 114 115 void bt_sysfs_cleanup(void) 116 { 117 class_destroy(bt_class); 118 } 119