Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6
[linux-2.6] / net / bluetooth / hci_sysfs.c
1 /* Bluetooth HCI driver model support. */
2
3 #include <linux/config.h>
4 #include <linux/kernel.h>
5 #include <linux/init.h>
6
7 #include <net/bluetooth/bluetooth.h>
8 #include <net/bluetooth/hci_core.h>
9
10 #ifndef CONFIG_BT_HCI_CORE_DEBUG
11 #undef  BT_DBG
12 #define BT_DBG(D...)
13 #endif
14
15 static ssize_t show_name(struct class_device *cdev, char *buf)
16 {
17         struct hci_dev *hdev = class_get_devdata(cdev);
18         return sprintf(buf, "%s\n", hdev->name);
19 }
20
21 static ssize_t show_type(struct class_device *cdev, char *buf)
22 {
23         struct hci_dev *hdev = class_get_devdata(cdev);
24         return sprintf(buf, "%d\n", hdev->type);
25 }
26
27 static ssize_t show_address(struct class_device *cdev, char *buf)
28 {
29         struct hci_dev *hdev = class_get_devdata(cdev);
30         bdaddr_t bdaddr;
31         baswap(&bdaddr, &hdev->bdaddr);
32         return sprintf(buf, "%s\n", batostr(&bdaddr));
33 }
34
35 static ssize_t show_flags(struct class_device *cdev, char *buf)
36 {
37         struct hci_dev *hdev = class_get_devdata(cdev);
38         return sprintf(buf, "0x%lx\n", hdev->flags);
39 }
40
41 static ssize_t show_inquiry_cache(struct class_device *cdev, char *buf)
42 {
43         struct hci_dev *hdev = class_get_devdata(cdev);
44         struct inquiry_cache *cache = &hdev->inq_cache;
45         struct inquiry_entry *e;
46         int n = 0;
47
48         hci_dev_lock_bh(hdev);
49
50         for (e = cache->list; e; e = e->next) {
51                 struct inquiry_data *data = &e->data;
52                 bdaddr_t bdaddr;
53                 baswap(&bdaddr, &data->bdaddr);
54                 n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %u\n",
55                                 batostr(&bdaddr),
56                                 data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode,
57                                 data->dev_class[2], data->dev_class[1], data->dev_class[0],
58                                 __le16_to_cpu(data->clock_offset), data->rssi, e->timestamp);
59         }
60
61         hci_dev_unlock_bh(hdev);
62         return n;
63 }
64
65 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
66 static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
67 static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
68 static CLASS_DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
69 static CLASS_DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
70
71 static struct class_device_attribute *bt_attrs[] = {
72         &class_device_attr_name,
73         &class_device_attr_type,
74         &class_device_attr_address,
75         &class_device_attr_flags,
76         &class_device_attr_inquiry_cache,
77         NULL
78 };
79
80 #ifdef CONFIG_HOTPLUG
81 static int bt_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
82 {
83         struct hci_dev *hdev = class_get_devdata(cdev);
84         int n, i = 0;
85
86         envp[i++] = buf;
87         n = snprintf(buf, size, "INTERFACE=%s", hdev->name) + 1;
88         buf += n;
89         size -= n;
90
91         if ((size <= 0) || (i >= num_envp))
92                 return -ENOMEM;
93
94         envp[i] = NULL;
95         return 0;
96 }
97 #endif
98
99 static void bt_release(struct class_device *cdev)
100 {
101         struct hci_dev *hdev = class_get_devdata(cdev);
102
103         kfree(hdev);
104 }
105
106 struct class bt_class = {
107         .name           = "bluetooth",
108         .release        = bt_release,
109 #ifdef CONFIG_HOTPLUG
110         .uevent         = bt_uevent,
111 #endif
112 };
113
114 EXPORT_SYMBOL_GPL(bt_class);
115
116 int hci_register_sysfs(struct hci_dev *hdev)
117 {
118         struct class_device *cdev = &hdev->class_dev;
119         unsigned int i;
120         int err;
121
122         BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
123
124         cdev->class = &bt_class;
125         class_set_devdata(cdev, hdev);
126
127         strlcpy(cdev->class_id, hdev->name, BUS_ID_SIZE);
128         err = class_device_register(cdev);
129         if (err < 0)
130                 return err;
131
132         for (i = 0; bt_attrs[i]; i++)
133                 class_device_create_file(cdev, bt_attrs[i]);
134
135         return 0;
136 }
137
138 void hci_unregister_sysfs(struct hci_dev *hdev)
139 {
140         struct class_device * cdev = &hdev->class_dev;
141
142         BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
143
144         class_device_del(cdev);
145 }
146
147 int __init bt_sysfs_init(void)
148 {
149         return class_register(&bt_class);
150 }
151
152 void __exit bt_sysfs_cleanup(void)
153 {
154         class_unregister(&bt_class);
155 }