aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/hci_sysfs.c')
-rw-r--r--net/bluetooth/hci_sysfs.c125
1 files changed, 88 insertions, 37 deletions
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 2bc6f6a8de68..0e8e1a59856c 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -1,13 +1,18 @@
1/* Bluetooth HCI driver model support. */ 1/* Bluetooth HCI driver model support. */
2 2
3#include <linux/kernel.h> 3#include <linux/kernel.h>
4#include <linux/slab.h>
4#include <linux/init.h> 5#include <linux/init.h>
6#include <linux/debugfs.h>
7#include <linux/seq_file.h>
5 8
6#include <net/bluetooth/bluetooth.h> 9#include <net/bluetooth/bluetooth.h>
7#include <net/bluetooth/hci_core.h> 10#include <net/bluetooth/hci_core.h>
8 11
9struct class *bt_class = NULL; 12static struct class *bt_class;
10EXPORT_SYMBOL_GPL(bt_class); 13
14struct dentry *bt_debugfs = NULL;
15EXPORT_SYMBOL_GPL(bt_debugfs);
11 16
12static struct workqueue_struct *bt_workq; 17static struct workqueue_struct *bt_workq;
13 18
@@ -166,9 +171,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
166 queue_work(bt_workq, &conn->work_del); 171 queue_work(bt_workq, &conn->work_del);
167} 172}
168 173
169static inline char *host_typetostr(int type) 174static inline char *host_bustostr(int bus)
170{ 175{
171 switch (type) { 176 switch (bus) {
172 case HCI_VIRTUAL: 177 case HCI_VIRTUAL:
173 return "VIRTUAL"; 178 return "VIRTUAL";
174 case HCI_USB: 179 case HCI_USB:
@@ -188,10 +193,28 @@ static inline char *host_typetostr(int type)
188 } 193 }
189} 194}
190 195
196static inline char *host_typetostr(int type)
197{
198 switch (type) {
199 case HCI_BREDR:
200 return "BR/EDR";
201 case HCI_80211:
202 return "802.11";
203 default:
204 return "UNKNOWN";
205 }
206}
207
208static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf)
209{
210 struct hci_dev *hdev = dev_get_drvdata(dev);
211 return sprintf(buf, "%s\n", host_bustostr(hdev->bus));
212}
213
191static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) 214static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
192{ 215{
193 struct hci_dev *hdev = dev_get_drvdata(dev); 216 struct hci_dev *hdev = dev_get_drvdata(dev);
194 return sprintf(buf, "%s\n", host_typetostr(hdev->type)); 217 return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type));
195} 218}
196 219
197static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) 220static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -251,32 +274,6 @@ static ssize_t show_hci_revision(struct device *dev, struct device_attribute *at
251 return sprintf(buf, "%d\n", hdev->hci_rev); 274 return sprintf(buf, "%d\n", hdev->hci_rev);
252} 275}
253 276
254static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf)
255{
256 struct hci_dev *hdev = dev_get_drvdata(dev);
257 struct inquiry_cache *cache = &hdev->inq_cache;
258 struct inquiry_entry *e;
259 int n = 0;
260
261 hci_dev_lock_bh(hdev);
262
263 for (e = cache->list; e; e = e->next) {
264 struct inquiry_data *data = &e->data;
265 bdaddr_t bdaddr;
266 baswap(&bdaddr, &data->bdaddr);
267 n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
268 batostr(&bdaddr),
269 data->pscan_rep_mode, data->pscan_period_mode,
270 data->pscan_mode, data->dev_class[2],
271 data->dev_class[1], data->dev_class[0],
272 __le16_to_cpu(data->clock_offset),
273 data->rssi, data->ssp_mode, e->timestamp);
274 }
275
276 hci_dev_unlock_bh(hdev);
277 return n;
278}
279
280static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf) 277static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf)
281{ 278{
282 struct hci_dev *hdev = dev_get_drvdata(dev); 279 struct hci_dev *hdev = dev_get_drvdata(dev);
@@ -355,6 +352,7 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib
355 return count; 352 return count;
356} 353}
357 354
355static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL);
358static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); 356static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
359static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 357static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
360static DEVICE_ATTR(class, S_IRUGO, show_class, NULL); 358static DEVICE_ATTR(class, S_IRUGO, show_class, NULL);
@@ -363,7 +361,6 @@ static DEVICE_ATTR(features, S_IRUGO, show_features, NULL);
363static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL); 361static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
364static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); 362static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
365static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); 363static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
366static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
367 364
368static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, 365static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
369 show_idle_timeout, store_idle_timeout); 366 show_idle_timeout, store_idle_timeout);
@@ -373,6 +370,7 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
373 show_sniff_min_interval, store_sniff_min_interval); 370 show_sniff_min_interval, store_sniff_min_interval);
374 371
375static struct attribute *bt_host_attrs[] = { 372static struct attribute *bt_host_attrs[] = {
373 &dev_attr_bus.attr,
376 &dev_attr_type.attr, 374 &dev_attr_type.attr,
377 &dev_attr_name.attr, 375 &dev_attr_name.attr,
378 &dev_attr_class.attr, 376 &dev_attr_class.attr,
@@ -381,7 +379,6 @@ static struct attribute *bt_host_attrs[] = {
381 &dev_attr_manufacturer.attr, 379 &dev_attr_manufacturer.attr,
382 &dev_attr_hci_version.attr, 380 &dev_attr_hci_version.attr,
383 &dev_attr_hci_revision.attr, 381 &dev_attr_hci_revision.attr,
384 &dev_attr_inquiry_cache.attr,
385 &dev_attr_idle_timeout.attr, 382 &dev_attr_idle_timeout.attr,
386 &dev_attr_sniff_max_interval.attr, 383 &dev_attr_sniff_max_interval.attr,
387 &dev_attr_sniff_min_interval.attr, 384 &dev_attr_sniff_min_interval.attr,
@@ -409,12 +406,50 @@ static struct device_type bt_host = {
409 .release = bt_host_release, 406 .release = bt_host_release,
410}; 407};
411 408
409static int inquiry_cache_show(struct seq_file *f, void *p)
410{
411 struct hci_dev *hdev = f->private;
412 struct inquiry_cache *cache = &hdev->inq_cache;
413 struct inquiry_entry *e;
414
415 hci_dev_lock_bh(hdev);
416
417 for (e = cache->list; e; e = e->next) {
418 struct inquiry_data *data = &e->data;
419 bdaddr_t bdaddr;
420 baswap(&bdaddr, &data->bdaddr);
421 seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
422 batostr(&bdaddr),
423 data->pscan_rep_mode, data->pscan_period_mode,
424 data->pscan_mode, data->dev_class[2],
425 data->dev_class[1], data->dev_class[0],
426 __le16_to_cpu(data->clock_offset),
427 data->rssi, data->ssp_mode, e->timestamp);
428 }
429
430 hci_dev_unlock_bh(hdev);
431
432 return 0;
433}
434
435static int inquiry_cache_open(struct inode *inode, struct file *file)
436{
437 return single_open(file, inquiry_cache_show, inode->i_private);
438}
439
440static const struct file_operations inquiry_cache_fops = {
441 .open = inquiry_cache_open,
442 .read = seq_read,
443 .llseek = seq_lseek,
444 .release = single_release,
445};
446
412int hci_register_sysfs(struct hci_dev *hdev) 447int hci_register_sysfs(struct hci_dev *hdev)
413{ 448{
414 struct device *dev = &hdev->dev; 449 struct device *dev = &hdev->dev;
415 int err; 450 int err;
416 451
417 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); 452 BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
418 453
419 dev->type = &bt_host; 454 dev->type = &bt_host;
420 dev->class = bt_class; 455 dev->class = bt_class;
@@ -428,12 +463,24 @@ int hci_register_sysfs(struct hci_dev *hdev)
428 if (err < 0) 463 if (err < 0)
429 return err; 464 return err;
430 465
466 if (!bt_debugfs)
467 return 0;
468
469 hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);
470 if (!hdev->debugfs)
471 return 0;
472
473 debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
474 hdev, &inquiry_cache_fops);
475
431 return 0; 476 return 0;
432} 477}
433 478
434void hci_unregister_sysfs(struct hci_dev *hdev) 479void hci_unregister_sysfs(struct hci_dev *hdev)
435{ 480{
436 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); 481 BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
482
483 debugfs_remove_recursive(hdev->debugfs);
437 484
438 device_del(&hdev->dev); 485 device_del(&hdev->dev);
439} 486}
@@ -444,6 +491,8 @@ int __init bt_sysfs_init(void)
444 if (!bt_workq) 491 if (!bt_workq)
445 return -ENOMEM; 492 return -ENOMEM;
446 493
494 bt_debugfs = debugfs_create_dir("bluetooth", NULL);
495
447 bt_class = class_create(THIS_MODULE, "bluetooth"); 496 bt_class = class_create(THIS_MODULE, "bluetooth");
448 if (IS_ERR(bt_class)) { 497 if (IS_ERR(bt_class)) {
449 destroy_workqueue(bt_workq); 498 destroy_workqueue(bt_workq);
@@ -455,7 +504,9 @@ int __init bt_sysfs_init(void)
455 504
456void bt_sysfs_cleanup(void) 505void bt_sysfs_cleanup(void)
457{ 506{
458 destroy_workqueue(bt_workq);
459
460 class_destroy(bt_class); 507 class_destroy(bt_class);
508
509 debugfs_remove_recursive(bt_debugfs);
510
511 destroy_workqueue(bt_workq);
461} 512}