Bluetooth: Move common debugfs file creation into hci_debugfs.c
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / hci_debugfs.c
1 /*
2    BlueZ - Bluetooth protocol stack for Linux
3
4    Copyright (C) 2014 Intel Corporation
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License version 2 as
8    published by the Free Software Foundation;
9
10    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
19    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21    SOFTWARE IS DISCLAIMED.
22 */
23
24 #include <linux/debugfs.h>
25
26 #include <net/bluetooth/bluetooth.h>
27 #include <net/bluetooth/hci_core.h>
28
29 #include "hci_debugfs.h"
30
31 static int features_show(struct seq_file *f, void *ptr)
32 {
33         struct hci_dev *hdev = f->private;
34         u8 p;
35
36         hci_dev_lock(hdev);
37         for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
38                 seq_printf(f, "%2u: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
39                            "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", p,
40                            hdev->features[p][0], hdev->features[p][1],
41                            hdev->features[p][2], hdev->features[p][3],
42                            hdev->features[p][4], hdev->features[p][5],
43                            hdev->features[p][6], hdev->features[p][7]);
44         }
45         if (lmp_le_capable(hdev))
46                 seq_printf(f, "LE: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
47                            "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
48                            hdev->le_features[0], hdev->le_features[1],
49                            hdev->le_features[2], hdev->le_features[3],
50                            hdev->le_features[4], hdev->le_features[5],
51                            hdev->le_features[6], hdev->le_features[7]);
52         hci_dev_unlock(hdev);
53
54         return 0;
55 }
56
57 static int features_open(struct inode *inode, struct file *file)
58 {
59         return single_open(file, features_show, inode->i_private);
60 }
61
62 static const struct file_operations features_fops = {
63         .open           = features_open,
64         .read           = seq_read,
65         .llseek         = seq_lseek,
66         .release        = single_release,
67 };
68
69 static int device_list_show(struct seq_file *f, void *ptr)
70 {
71         struct hci_dev *hdev = f->private;
72         struct hci_conn_params *p;
73         struct bdaddr_list *b;
74
75         hci_dev_lock(hdev);
76         list_for_each_entry(b, &hdev->whitelist, list)
77                 seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
78         list_for_each_entry(p, &hdev->le_conn_params, list) {
79                 seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type,
80                            p->auto_connect);
81         }
82         hci_dev_unlock(hdev);
83
84         return 0;
85 }
86
87 static int device_list_open(struct inode *inode, struct file *file)
88 {
89         return single_open(file, device_list_show, inode->i_private);
90 }
91
92 static const struct file_operations device_list_fops = {
93         .open           = device_list_open,
94         .read           = seq_read,
95         .llseek         = seq_lseek,
96         .release        = single_release,
97 };
98
99 static int blacklist_show(struct seq_file *f, void *p)
100 {
101         struct hci_dev *hdev = f->private;
102         struct bdaddr_list *b;
103
104         hci_dev_lock(hdev);
105         list_for_each_entry(b, &hdev->blacklist, list)
106                 seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
107         hci_dev_unlock(hdev);
108
109         return 0;
110 }
111
112 static int blacklist_open(struct inode *inode, struct file *file)
113 {
114         return single_open(file, blacklist_show, inode->i_private);
115 }
116
117 static const struct file_operations blacklist_fops = {
118         .open           = blacklist_open,
119         .read           = seq_read,
120         .llseek         = seq_lseek,
121         .release        = single_release,
122 };
123
124 static int uuids_show(struct seq_file *f, void *p)
125 {
126         struct hci_dev *hdev = f->private;
127         struct bt_uuid *uuid;
128
129         hci_dev_lock(hdev);
130         list_for_each_entry(uuid, &hdev->uuids, list) {
131                 u8 i, val[16];
132
133                 /* The Bluetooth UUID values are stored in big endian,
134                  * but with reversed byte order. So convert them into
135                  * the right order for the %pUb modifier.
136                  */
137                 for (i = 0; i < 16; i++)
138                         val[i] = uuid->uuid[15 - i];
139
140                 seq_printf(f, "%pUb\n", val);
141         }
142         hci_dev_unlock(hdev);
143
144        return 0;
145 }
146
147 static int uuids_open(struct inode *inode, struct file *file)
148 {
149         return single_open(file, uuids_show, inode->i_private);
150 }
151
152 static const struct file_operations uuids_fops = {
153         .open           = uuids_open,
154         .read           = seq_read,
155         .llseek         = seq_lseek,
156         .release        = single_release,
157 };
158
159 static int conn_info_min_age_set(void *data, u64 val)
160 {
161         struct hci_dev *hdev = data;
162
163         if (val == 0 || val > hdev->conn_info_max_age)
164                 return -EINVAL;
165
166         hci_dev_lock(hdev);
167         hdev->conn_info_min_age = val;
168         hci_dev_unlock(hdev);
169
170         return 0;
171 }
172
173 static int conn_info_min_age_get(void *data, u64 *val)
174 {
175         struct hci_dev *hdev = data;
176
177         hci_dev_lock(hdev);
178         *val = hdev->conn_info_min_age;
179         hci_dev_unlock(hdev);
180
181         return 0;
182 }
183
184 DEFINE_SIMPLE_ATTRIBUTE(conn_info_min_age_fops, conn_info_min_age_get,
185                         conn_info_min_age_set, "%llu\n");
186
187 static int conn_info_max_age_set(void *data, u64 val)
188 {
189         struct hci_dev *hdev = data;
190
191         if (val == 0 || val < hdev->conn_info_min_age)
192                 return -EINVAL;
193
194         hci_dev_lock(hdev);
195         hdev->conn_info_max_age = val;
196         hci_dev_unlock(hdev);
197
198         return 0;
199 }
200
201 static int conn_info_max_age_get(void *data, u64 *val)
202 {
203         struct hci_dev *hdev = data;
204
205         hci_dev_lock(hdev);
206         *val = hdev->conn_info_max_age;
207         hci_dev_unlock(hdev);
208
209         return 0;
210 }
211
212 DEFINE_SIMPLE_ATTRIBUTE(conn_info_max_age_fops, conn_info_max_age_get,
213                         conn_info_max_age_set, "%llu\n");
214
215 void hci_debugfs_create_common(struct hci_dev *hdev)
216 {
217         debugfs_create_file("features", 0444, hdev->debugfs, hdev,
218                             &features_fops);
219         debugfs_create_u16("manufacturer", 0444, hdev->debugfs,
220                            &hdev->manufacturer);
221         debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
222         debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
223         debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
224                             &device_list_fops);
225         debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
226                             &blacklist_fops);
227         debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
228
229         debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
230                             &conn_info_min_age_fops);
231         debugfs_create_file("conn_info_max_age", 0644, hdev->debugfs, hdev,
232                             &conn_info_max_age_fops);
233 }
234
235 void hci_debugfs_create_bredr(struct hci_dev *hdev)
236 {
237 }
238
239 void hci_debugfs_create_le(struct hci_dev *hdev)
240 {
241 }