linux/net/bluetooth/hci_sysfs.c
<<
>>
Prefs
   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
   9static struct class *bt_class;
  10
  11static void bt_link_release(struct device *dev)
  12{
  13        struct hci_conn *conn = to_hci_conn(dev);
  14        kfree(conn);
  15}
  16
  17static 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 */
  27static int __match_tty(struct device *dev, void *data)
  28{
  29        return !strncmp(dev_name(dev), "rfcomm", 6);
  30}
  31
  32void 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
  45void 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
  61void 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
  83static 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
  92static const struct device_type bt_host = {
  93        .name    = "host",
  94        .release = bt_host_release,
  95};
  96
  97void 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
 108int __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
 115void bt_sysfs_cleanup(void)
 116{
 117        class_destroy(bt_class);
 118}
 119