Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6
This commit is contained in:
commit
46976c042b
21 changed files with 131 additions and 63 deletions
|
@ -143,6 +143,8 @@ static int ath3k_probe(struct usb_interface *intf,
|
||||||
usb_set_intfdata(intf, data);
|
usb_set_intfdata(intf, data);
|
||||||
if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) {
|
if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) {
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
|
kfree(data->fw_data);
|
||||||
|
kfree(data);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
#define VERSION "1.2"
|
#define VERSION "1.2"
|
||||||
|
|
||||||
static struct usb_device_id bcm203x_table[] = {
|
static const struct usb_device_id bcm203x_table[] = {
|
||||||
/* Broadcom Blutonium (BCM2033) */
|
/* Broadcom Blutonium (BCM2033) */
|
||||||
{ USB_DEVICE(0x0a5c, 0x2033) },
|
{ USB_DEVICE(0x0a5c, 0x2033) },
|
||||||
|
|
||||||
|
|
|
@ -703,7 +703,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
||||||
hdev->type = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hdev->driver_data = data;
|
hdev->driver_data = data;
|
||||||
SET_HCIDEV_DEV(hdev, &intf->dev);
|
SET_HCIDEV_DEV(hdev, &intf->dev);
|
||||||
|
|
||||||
|
|
|
@ -736,7 +736,7 @@ static int bluecard_open(bluecard_info_t *info)
|
||||||
|
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->type = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hdev->driver_data = info;
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
|
|
|
@ -469,7 +469,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev->type = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hdev->driver_data = data;
|
hdev->driver_data = data;
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
|
@ -582,7 +582,7 @@ static int bt3c_open(bt3c_info_t *info)
|
||||||
|
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->type = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hdev->driver_data = info;
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
#include "btmrvl_drv.h"
|
#include "btmrvl_drv.h"
|
||||||
|
|
||||||
struct btmrvl_debugfs_data {
|
struct btmrvl_debugfs_data {
|
||||||
struct dentry *root_dir, *config_dir, *status_dir;
|
struct dentry *config_dir;
|
||||||
|
struct dentry *status_dir;
|
||||||
|
|
||||||
/* config */
|
/* config */
|
||||||
struct dentry *psmode;
|
struct dentry *psmode;
|
||||||
|
@ -363,6 +364,9 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||||
struct btmrvl_private *priv = hdev->driver_data;
|
struct btmrvl_private *priv = hdev->driver_data;
|
||||||
struct btmrvl_debugfs_data *dbg;
|
struct btmrvl_debugfs_data *dbg;
|
||||||
|
|
||||||
|
if (!hdev->debugfs)
|
||||||
|
return;
|
||||||
|
|
||||||
dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
|
dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
|
||||||
priv->debugfs_data = dbg;
|
priv->debugfs_data = dbg;
|
||||||
|
|
||||||
|
@ -371,9 +375,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg->root_dir = debugfs_create_dir("btmrvl", NULL);
|
dbg->config_dir = debugfs_create_dir("config", hdev->debugfs);
|
||||||
|
|
||||||
dbg->config_dir = debugfs_create_dir("config", dbg->root_dir);
|
|
||||||
|
|
||||||
dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,
|
dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,
|
||||||
hdev->driver_data, &btmrvl_psmode_fops);
|
hdev->driver_data, &btmrvl_psmode_fops);
|
||||||
|
@ -388,7 +390,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||||
dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
|
dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
|
||||||
hdev->driver_data, &btmrvl_hscfgcmd_fops);
|
hdev->driver_data, &btmrvl_hscfgcmd_fops);
|
||||||
|
|
||||||
dbg->status_dir = debugfs_create_dir("status", dbg->root_dir);
|
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
|
||||||
dbg->curpsmode = debugfs_create_file("curpsmode", 0444,
|
dbg->curpsmode = debugfs_create_file("curpsmode", 0444,
|
||||||
dbg->status_dir,
|
dbg->status_dir,
|
||||||
hdev->driver_data,
|
hdev->driver_data,
|
||||||
|
@ -425,7 +427,5 @@ void btmrvl_debugfs_remove(struct hci_dev *hdev)
|
||||||
debugfs_remove(dbg->txdnldready);
|
debugfs_remove(dbg->txdnldready);
|
||||||
debugfs_remove(dbg->status_dir);
|
debugfs_remove(dbg->status_dir);
|
||||||
|
|
||||||
debugfs_remove(dbg->root_dir);
|
|
||||||
|
|
||||||
kfree(dbg);
|
kfree(dbg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -563,7 +563,7 @@ struct btmrvl_private *btmrvl_add_card(void *card)
|
||||||
|
|
||||||
priv->btmrvl_dev.tx_dnld_rdy = true;
|
priv->btmrvl_dev.tx_dnld_rdy = true;
|
||||||
|
|
||||||
hdev->type = HCI_SDIO;
|
hdev->bus = HCI_SDIO;
|
||||||
hdev->open = btmrvl_open;
|
hdev->open = btmrvl_open;
|
||||||
hdev->close = btmrvl_close;
|
hdev->close = btmrvl_close;
|
||||||
hdev->flush = btmrvl_flush;
|
hdev->flush = btmrvl_flush;
|
||||||
|
|
|
@ -976,7 +976,7 @@ static struct sdio_driver bt_mrvl_sdio = {
|
||||||
.remove = btmrvl_sdio_remove,
|
.remove = btmrvl_sdio_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int btmrvl_sdio_init_module(void)
|
static int __init btmrvl_sdio_init_module(void)
|
||||||
{
|
{
|
||||||
if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
|
if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
|
||||||
BT_ERR("SDIO Driver Registration Failed");
|
BT_ERR("SDIO Driver Registration Failed");
|
||||||
|
@ -989,7 +989,7 @@ static int btmrvl_sdio_init_module(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void btmrvl_sdio_exit_module(void)
|
static void __exit btmrvl_sdio_exit_module(void)
|
||||||
{
|
{
|
||||||
/* Set the flag as user is removing this module. */
|
/* Set the flag as user is removing this module. */
|
||||||
user_rmmod = 1;
|
user_rmmod = 1;
|
||||||
|
|
|
@ -326,7 +326,7 @@ static int btsdio_probe(struct sdio_func *func,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev->type = HCI_SDIO;
|
hdev->bus = HCI_SDIO;
|
||||||
hdev->driver_data = data;
|
hdev->driver_data = data;
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
|
@ -500,7 +500,7 @@ static int btuart_open(btuart_info_t *info)
|
||||||
|
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->type = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hdev->driver_data = info;
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
|
|
|
@ -939,7 +939,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev->type = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hdev->driver_data = data;
|
hdev->driver_data = data;
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
|
@ -485,7 +485,7 @@ static int dtl1_open(dtl1_info_t *info)
|
||||||
|
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->type = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hdev->driver_data = info;
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
||||||
|
|
||||||
hu->hdev = hdev;
|
hu->hdev = hdev;
|
||||||
|
|
||||||
hdev->type = HCI_UART;
|
hdev->bus = HCI_UART;
|
||||||
hdev->driver_data = hu;
|
hdev->driver_data = hu;
|
||||||
|
|
||||||
hdev->open = hci_uart_open;
|
hdev->open = hci_uart_open;
|
||||||
|
|
|
@ -236,7 +236,7 @@ static int vhci_open(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
||||||
hdev->type = HCI_VIRTUAL;
|
hdev->bus = HCI_VIRTUAL;
|
||||||
hdev->driver_data = data;
|
hdev->driver_data = data;
|
||||||
|
|
||||||
hdev->open = vhci_open_dev;
|
hdev->open = vhci_open_dev;
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#define HCI_NOTIFY_CONN_DEL 2
|
#define HCI_NOTIFY_CONN_DEL 2
|
||||||
#define HCI_NOTIFY_VOICE_SETTING 3
|
#define HCI_NOTIFY_VOICE_SETTING 3
|
||||||
|
|
||||||
/* HCI device types */
|
/* HCI bus types */
|
||||||
#define HCI_VIRTUAL 0
|
#define HCI_VIRTUAL 0
|
||||||
#define HCI_USB 1
|
#define HCI_USB 1
|
||||||
#define HCI_PCCARD 2
|
#define HCI_PCCARD 2
|
||||||
|
@ -52,6 +52,10 @@
|
||||||
#define HCI_PCI 5
|
#define HCI_PCI 5
|
||||||
#define HCI_SDIO 6
|
#define HCI_SDIO 6
|
||||||
|
|
||||||
|
/* HCI controller types */
|
||||||
|
#define HCI_BREDR 0x00
|
||||||
|
#define HCI_80211 0x01
|
||||||
|
|
||||||
/* HCI device quirks */
|
/* HCI device quirks */
|
||||||
enum {
|
enum {
|
||||||
HCI_QUIRK_NO_RESET,
|
HCI_QUIRK_NO_RESET,
|
||||||
|
|
|
@ -70,7 +70,8 @@ struct hci_dev {
|
||||||
char name[8];
|
char name[8];
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
__u16 id;
|
__u16 id;
|
||||||
__u8 type;
|
__u8 bus;
|
||||||
|
__u8 dev_type;
|
||||||
bdaddr_t bdaddr;
|
bdaddr_t bdaddr;
|
||||||
__u8 dev_name[248];
|
__u8 dev_name[248];
|
||||||
__u8 dev_class[3];
|
__u8 dev_class[3];
|
||||||
|
@ -134,6 +135,8 @@ struct hci_dev {
|
||||||
|
|
||||||
atomic_t promisc;
|
atomic_t promisc;
|
||||||
|
|
||||||
|
struct dentry *debugfs;
|
||||||
|
|
||||||
struct device *parent;
|
struct device *parent;
|
||||||
struct device dev;
|
struct device dev;
|
||||||
|
|
||||||
|
|
|
@ -491,6 +491,10 @@ int hci_dev_open(__u16 dev)
|
||||||
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
|
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
|
||||||
set_bit(HCI_RAW, &hdev->flags);
|
set_bit(HCI_RAW, &hdev->flags);
|
||||||
|
|
||||||
|
/* Treat all non BR/EDR controllers as raw devices for now */
|
||||||
|
if (hdev->dev_type != HCI_BREDR)
|
||||||
|
set_bit(HCI_RAW, &hdev->flags);
|
||||||
|
|
||||||
if (hdev->open(hdev)) {
|
if (hdev->open(hdev)) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -797,7 +801,7 @@ int hci_get_dev_info(void __user *arg)
|
||||||
|
|
||||||
strcpy(di.name, hdev->name);
|
strcpy(di.name, hdev->name);
|
||||||
di.bdaddr = hdev->bdaddr;
|
di.bdaddr = hdev->bdaddr;
|
||||||
di.type = hdev->type;
|
di.type = (hdev->bus & 0x0f) | (hdev->dev_type << 4);
|
||||||
di.flags = hdev->flags;
|
di.flags = hdev->flags;
|
||||||
di.pkt_type = hdev->pkt_type;
|
di.pkt_type = hdev->pkt_type;
|
||||||
di.acl_mtu = hdev->acl_mtu;
|
di.acl_mtu = hdev->acl_mtu;
|
||||||
|
@ -869,8 +873,8 @@ int hci_register_dev(struct hci_dev *hdev)
|
||||||
struct list_head *head = &hci_dev_list, *p;
|
struct list_head *head = &hci_dev_list, *p;
|
||||||
int i, id = 0;
|
int i, id = 0;
|
||||||
|
|
||||||
BT_DBG("%p name %s type %d owner %p", hdev, hdev->name,
|
BT_DBG("%p name %s bus %d owner %p", hdev, hdev->name,
|
||||||
hdev->type, hdev->owner);
|
hdev->bus, hdev->owner);
|
||||||
|
|
||||||
if (!hdev->open || !hdev->close || !hdev->destruct)
|
if (!hdev->open || !hdev->close || !hdev->destruct)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -946,7 +950,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
|
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
|
||||||
|
|
||||||
write_lock_bh(&hci_dev_list_lock);
|
write_lock_bh(&hci_dev_list_lock);
|
||||||
list_del(&hdev->list);
|
list_del(&hdev->list);
|
||||||
|
|
|
@ -1698,6 +1698,7 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
|
||||||
hci_conn_add_sysfs(conn);
|
hci_conn_add_sysfs(conn);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x11: /* Unsupported Feature or Parameter Value */
|
||||||
case 0x1c: /* SCO interval rejected */
|
case 0x1c: /* SCO interval rejected */
|
||||||
case 0x1a: /* Unsupported Remote Feature */
|
case 0x1a: /* Unsupported Remote Feature */
|
||||||
case 0x1f: /* Unspecified error */
|
case 0x1f: /* Unspecified error */
|
||||||
|
|
|
@ -329,6 +329,9 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask & HCI_CMSG_TSTAMP) {
|
if (mask & HCI_CMSG_TSTAMP) {
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
struct compat_timeval ctv;
|
||||||
|
#endif
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
void *data;
|
void *data;
|
||||||
int len;
|
int len;
|
||||||
|
@ -339,7 +342,6 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_
|
||||||
len = sizeof(tv);
|
len = sizeof(tv);
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
if (msg->msg_flags & MSG_CMSG_COMPAT) {
|
if (msg->msg_flags & MSG_CMSG_COMPAT) {
|
||||||
struct compat_timeval ctv;
|
|
||||||
ctv.tv_sec = tv.tv_sec;
|
ctv.tv_sec = tv.tv_sec;
|
||||||
ctv.tv_usec = tv.tv_usec;
|
ctv.tv_usec = tv.tv_usec;
|
||||||
data = &ctv;
|
data = &ctv;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
|
@ -9,6 +10,9 @@
|
||||||
struct class *bt_class = NULL;
|
struct class *bt_class = NULL;
|
||||||
EXPORT_SYMBOL_GPL(bt_class);
|
EXPORT_SYMBOL_GPL(bt_class);
|
||||||
|
|
||||||
|
struct dentry *bt_debugfs = NULL;
|
||||||
|
EXPORT_SYMBOL_GPL(bt_debugfs);
|
||||||
|
|
||||||
static struct workqueue_struct *bt_workq;
|
static struct workqueue_struct *bt_workq;
|
||||||
|
|
||||||
static inline char *link_typetostr(int type)
|
static inline char *link_typetostr(int type)
|
||||||
|
@ -166,9 +170,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
||||||
queue_work(bt_workq, &conn->work_del);
|
queue_work(bt_workq, &conn->work_del);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *host_typetostr(int type)
|
static inline char *host_bustostr(int bus)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (bus) {
|
||||||
case HCI_VIRTUAL:
|
case HCI_VIRTUAL:
|
||||||
return "VIRTUAL";
|
return "VIRTUAL";
|
||||||
case HCI_USB:
|
case HCI_USB:
|
||||||
|
@ -188,10 +192,28 @@ static inline char *host_typetostr(int type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline char *host_typetostr(int type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case HCI_BREDR:
|
||||||
|
return "BR/EDR";
|
||||||
|
case HCI_80211:
|
||||||
|
return "802.11";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||||
|
return sprintf(buf, "%s\n", host_bustostr(hdev->bus));
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
|
static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||||
return sprintf(buf, "%s\n", host_typetostr(hdev->type));
|
return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
@ -251,32 +273,6 @@ static ssize_t show_hci_revision(struct device *dev, struct device_attribute *at
|
||||||
return sprintf(buf, "%d\n", hdev->hci_rev);
|
return sprintf(buf, "%d\n", hdev->hci_rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
|
||||||
struct inquiry_cache *cache = &hdev->inq_cache;
|
|
||||||
struct inquiry_entry *e;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
|
||||||
|
|
||||||
for (e = cache->list; e; e = e->next) {
|
|
||||||
struct inquiry_data *data = &e->data;
|
|
||||||
bdaddr_t bdaddr;
|
|
||||||
baswap(&bdaddr, &data->bdaddr);
|
|
||||||
n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
|
|
||||||
batostr(&bdaddr),
|
|
||||||
data->pscan_rep_mode, data->pscan_period_mode,
|
|
||||||
data->pscan_mode, data->dev_class[2],
|
|
||||||
data->dev_class[1], data->dev_class[0],
|
|
||||||
__le16_to_cpu(data->clock_offset),
|
|
||||||
data->rssi, data->ssp_mode, e->timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
hci_dev_unlock_bh(hdev);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf)
|
static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||||
|
@ -355,6 +351,7 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL);
|
||||||
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
|
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
|
||||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||||
static DEVICE_ATTR(class, S_IRUGO, show_class, NULL);
|
static DEVICE_ATTR(class, S_IRUGO, show_class, NULL);
|
||||||
|
@ -363,7 +360,6 @@ static DEVICE_ATTR(features, S_IRUGO, show_features, NULL);
|
||||||
static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
|
static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
|
||||||
static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
|
static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
|
||||||
static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
|
static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
|
||||||
static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
|
|
||||||
|
|
||||||
static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
|
static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
|
||||||
show_idle_timeout, store_idle_timeout);
|
show_idle_timeout, store_idle_timeout);
|
||||||
|
@ -373,6 +369,7 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
|
||||||
show_sniff_min_interval, store_sniff_min_interval);
|
show_sniff_min_interval, store_sniff_min_interval);
|
||||||
|
|
||||||
static struct attribute *bt_host_attrs[] = {
|
static struct attribute *bt_host_attrs[] = {
|
||||||
|
&dev_attr_bus.attr,
|
||||||
&dev_attr_type.attr,
|
&dev_attr_type.attr,
|
||||||
&dev_attr_name.attr,
|
&dev_attr_name.attr,
|
||||||
&dev_attr_class.attr,
|
&dev_attr_class.attr,
|
||||||
|
@ -381,7 +378,6 @@ static struct attribute *bt_host_attrs[] = {
|
||||||
&dev_attr_manufacturer.attr,
|
&dev_attr_manufacturer.attr,
|
||||||
&dev_attr_hci_version.attr,
|
&dev_attr_hci_version.attr,
|
||||||
&dev_attr_hci_revision.attr,
|
&dev_attr_hci_revision.attr,
|
||||||
&dev_attr_inquiry_cache.attr,
|
|
||||||
&dev_attr_idle_timeout.attr,
|
&dev_attr_idle_timeout.attr,
|
||||||
&dev_attr_sniff_max_interval.attr,
|
&dev_attr_sniff_max_interval.attr,
|
||||||
&dev_attr_sniff_min_interval.attr,
|
&dev_attr_sniff_min_interval.attr,
|
||||||
|
@ -409,12 +405,52 @@ static struct device_type bt_host = {
|
||||||
.release = bt_host_release,
|
.release = bt_host_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int inquiry_cache_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
file->private_data = inode->i_private;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct hci_dev *hdev = file->private_data;
|
||||||
|
struct inquiry_cache *cache = &hdev->inq_cache;
|
||||||
|
struct inquiry_entry *e;
|
||||||
|
char buf[4096];
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
|
for (e = cache->list; e; e = e->next) {
|
||||||
|
struct inquiry_data *data = &e->data;
|
||||||
|
bdaddr_t bdaddr;
|
||||||
|
baswap(&bdaddr, &data->bdaddr);
|
||||||
|
n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
|
||||||
|
batostr(&bdaddr),
|
||||||
|
data->pscan_rep_mode, data->pscan_period_mode,
|
||||||
|
data->pscan_mode, data->dev_class[2],
|
||||||
|
data->dev_class[1], data->dev_class[0],
|
||||||
|
__le16_to_cpu(data->clock_offset),
|
||||||
|
data->rssi, data->ssp_mode, e->timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_dev_unlock_bh(hdev);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(userbuf, count, ppos, buf, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations inquiry_cache_fops = {
|
||||||
|
.open = inquiry_cache_open,
|
||||||
|
.read = inquiry_cache_read,
|
||||||
|
};
|
||||||
|
|
||||||
int hci_register_sysfs(struct hci_dev *hdev)
|
int hci_register_sysfs(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &hdev->dev;
|
struct device *dev = &hdev->dev;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
|
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
|
||||||
|
|
||||||
dev->type = &bt_host;
|
dev->type = &bt_host;
|
||||||
dev->class = bt_class;
|
dev->class = bt_class;
|
||||||
|
@ -428,12 +464,24 @@ int hci_register_sysfs(struct hci_dev *hdev)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
if (!bt_debugfs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);
|
||||||
|
if (!hdev->debugfs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
|
||||||
|
hdev, &inquiry_cache_fops);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hci_unregister_sysfs(struct hci_dev *hdev)
|
void hci_unregister_sysfs(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
|
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
|
||||||
|
|
||||||
|
debugfs_remove_recursive(hdev->debugfs);
|
||||||
|
|
||||||
device_del(&hdev->dev);
|
device_del(&hdev->dev);
|
||||||
}
|
}
|
||||||
|
@ -444,6 +492,8 @@ int __init bt_sysfs_init(void)
|
||||||
if (!bt_workq)
|
if (!bt_workq)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
bt_debugfs = debugfs_create_dir("bluetooth", NULL);
|
||||||
|
|
||||||
bt_class = class_create(THIS_MODULE, "bluetooth");
|
bt_class = class_create(THIS_MODULE, "bluetooth");
|
||||||
if (IS_ERR(bt_class)) {
|
if (IS_ERR(bt_class)) {
|
||||||
destroy_workqueue(bt_workq);
|
destroy_workqueue(bt_workq);
|
||||||
|
@ -455,7 +505,9 @@ int __init bt_sysfs_init(void)
|
||||||
|
|
||||||
void bt_sysfs_cleanup(void)
|
void bt_sysfs_cleanup(void)
|
||||||
{
|
{
|
||||||
destroy_workqueue(bt_workq);
|
|
||||||
|
|
||||||
class_destroy(bt_class);
|
class_destroy(bt_class);
|
||||||
|
|
||||||
|
debugfs_remove_recursive(bt_debugfs);
|
||||||
|
|
||||||
|
destroy_workqueue(bt_workq);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue