Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

This commit is contained in:
John W. Linville 2012-08-10 15:13:12 -04:00
commit 57f784fed3
29 changed files with 418 additions and 200 deletions

View File

@ -177,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate memory for data structure");
return -ENOMEM;
@ -189,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
data->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!data->urb) {
BT_ERR("Can't allocate URB");
kfree(data);
return -ENOMEM;
}
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
BT_ERR("Mini driver request failed");
usb_free_urb(data->urb);
kfree(data);
return -EIO;
}
@ -209,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_ERR("Can't allocate memory for mini driver");
release_firmware(firmware);
usb_free_urb(data->urb);
kfree(data);
return -ENOMEM;
}
@ -224,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_ERR("Firmware request failed");
usb_free_urb(data->urb);
kfree(data->buffer);
kfree(data);
return -EIO;
}
@ -236,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
release_firmware(firmware);
usb_free_urb(data->urb);
kfree(data->buffer);
kfree(data);
return -ENOMEM;
}
@ -271,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
usb_free_urb(data->urb);
kfree(data->fw_data);
kfree(data->buffer);
kfree(data);
}
static struct usb_driver bcm203x_driver = {

View File

@ -653,7 +653,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
}
/* Initialize control structure and load firmware */
data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate memory for control structure");
goto done;
@ -674,7 +674,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
BT_ERR("Firmware request failed");
goto error;
goto done;
}
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
@ -690,7 +690,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
hdev = hci_alloc_dev();
if (!hdev) {
BT_ERR("Can't allocate HCI device");
goto error;
goto done;
}
data->hdev = hdev;
@ -708,7 +708,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
goto error;
goto done;
}
usb_set_intfdata(intf, data);
@ -718,9 +718,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
release:
release_firmware(firmware);
error:
kfree(data);
done:
return -EIO;
}
@ -741,7 +738,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
hci_unregister_dev(hdev);
hci_free_dev(hdev);
kfree(data);
}
static struct usb_driver bfusb_driver = {

View File

@ -849,7 +849,7 @@ static int bluecard_probe(struct pcmcia_device *link)
bluecard_info_t *info;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
@ -864,10 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
static void bluecard_detach(struct pcmcia_device *link)
{
bluecard_info_t *info = link->priv;
bluecard_release(link);
kfree(info);
}

View File

@ -443,7 +443,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -453,10 +453,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
init_usb_anchor(&data->rx_anchor);
hdev = hci_alloc_dev();
if (!hdev) {
kfree(data);
if (!hdev)
return -ENOMEM;
}
hdev->bus = HCI_USB;
hci_set_drvdata(hdev, data);
@ -475,7 +473,6 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
err = hci_register_dev(hdev);
if (err < 0) {
hci_free_dev(hdev);
kfree(data);
return err;
}
@ -500,7 +497,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
hci_free_dev(data->hdev);
kfree_skb(data->rx_skb[0]);
kfree_skb(data->rx_skb[1]);
kfree(data);
}
static struct usb_driver bpa10x_driver = {

View File

@ -638,7 +638,7 @@ static int bt3c_probe(struct pcmcia_device *link)
bt3c_info_t *info;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
@ -654,10 +654,7 @@ static int bt3c_probe(struct pcmcia_device *link)
static void bt3c_detach(struct pcmcia_device *link)
{
bt3c_info_t *info = link->priv;
bt3c_release(link);
kfree(info);
}
static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)

View File

@ -956,11 +956,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
id->vendor, id->device, id->class, func->num);
card = kzalloc(sizeof(*card), GFP_KERNEL);
if (!card) {
ret = -ENOMEM;
goto done;
}
card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
if (!card)
return -ENOMEM;
card->func = func;
@ -974,8 +972,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
if (btmrvl_sdio_register_dev(card) < 0) {
BT_ERR("Failed to register BT device!");
ret = -ENODEV;
goto free_card;
return -ENODEV;
}
/* Disable the interrupts on the card */
@ -1023,9 +1020,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
btmrvl_sdio_disable_host_int(card);
unreg_dev:
btmrvl_sdio_unregister_dev(card);
free_card:
kfree(card);
done:
return ret;
}
@ -1047,7 +1041,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
BT_DBG("unregester dev");
btmrvl_sdio_unregister_dev(card);
btmrvl_remove_card(card->priv);
kfree(card);
}
}
}

View File

@ -304,7 +304,7 @@ static int btsdio_probe(struct sdio_func *func,
tuple = tuple->next;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -315,10 +315,8 @@ static int btsdio_probe(struct sdio_func *func,
skb_queue_head_init(&data->txq);
hdev = hci_alloc_dev();
if (!hdev) {
kfree(data);
if (!hdev)
return -ENOMEM;
}
hdev->bus = HCI_SDIO;
hci_set_drvdata(hdev, data);
@ -340,7 +338,6 @@ static int btsdio_probe(struct sdio_func *func,
err = hci_register_dev(hdev);
if (err < 0) {
hci_free_dev(hdev);
kfree(data);
return err;
}
@ -366,7 +363,6 @@ static void btsdio_remove(struct sdio_func *func)
hci_unregister_dev(hdev);
hci_free_dev(hdev);
kfree(data);
}
static struct sdio_driver btsdio_driver = {

View File

@ -567,7 +567,7 @@ static int btuart_probe(struct pcmcia_device *link)
btuart_info_t *info;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
@ -583,10 +583,7 @@ static int btuart_probe(struct pcmcia_device *link)
static void btuart_detach(struct pcmcia_device *link)
{
btuart_info_t *info = link->priv;
btuart_release(link);
kfree(info);
}
static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)

View File

@ -952,7 +952,7 @@ static int btusb_probe(struct usb_interface *intf,
return -ENODEV;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -975,10 +975,8 @@ static int btusb_probe(struct usb_interface *intf,
}
}
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
kfree(data);
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
return -ENODEV;
}
data->cmdreq_type = USB_TYPE_CLASS;
@ -998,10 +996,8 @@ static int btusb_probe(struct usb_interface *intf,
init_usb_anchor(&data->deferred);
hdev = hci_alloc_dev();
if (!hdev) {
kfree(data);
if (!hdev)
return -ENOMEM;
}
hdev->bus = HCI_USB;
hci_set_drvdata(hdev, data);
@ -1069,7 +1065,6 @@ static int btusb_probe(struct usb_interface *intf,
data->isoc, data);
if (err < 0) {
hci_free_dev(hdev);
kfree(data);
return err;
}
}
@ -1077,7 +1072,6 @@ static int btusb_probe(struct usb_interface *intf,
err = hci_register_dev(hdev);
if (err < 0) {
hci_free_dev(hdev);
kfree(data);
return err;
}
@ -1110,7 +1104,6 @@ static void btusb_disconnect(struct usb_interface *intf)
usb_driver_release_interface(&btusb_driver, data->isoc);
hci_free_dev(hdev);
kfree(data);
}
#ifdef CONFIG_PM

View File

@ -297,16 +297,14 @@ static int bt_ti_probe(struct platform_device *pdev)
struct hci_dev *hdev;
int err;
hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL);
if (!hst)
return -ENOMEM;
/* Expose "hciX" device to user space */
hdev = hci_alloc_dev();
if (!hdev) {
kfree(hst);
if (!hdev)
return -ENOMEM;
}
BT_DBG("hdev %p", hdev);
@ -321,7 +319,6 @@ static int bt_ti_probe(struct platform_device *pdev)
err = hci_register_dev(hdev);
if (err < 0) {
BT_ERR("Can't register HCI device error %d", err);
kfree(hst);
hci_free_dev(hdev);
return err;
}
@ -347,7 +344,6 @@ static int bt_ti_remove(struct platform_device *pdev)
hci_unregister_dev(hdev);
hci_free_dev(hdev);
kfree(hst);
dev_set_drvdata(&pdev->dev, NULL);
return 0;

View File

@ -550,7 +550,7 @@ static int dtl1_probe(struct pcmcia_device *link)
dtl1_info_t *info;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
@ -569,7 +569,6 @@ static void dtl1_detach(struct pcmcia_device *link)
dtl1_close(info);
pcmcia_disable_device(link);
kfree(info);
}
static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)

View File

@ -27,6 +27,7 @@
#include <linux/poll.h>
#include <net/sock.h>
#include <linux/seq_file.h>
#ifndef AF_BLUETOOTH
#define AF_BLUETOOTH 31
@ -202,6 +203,10 @@ enum {
struct bt_sock_list {
struct hlist_head head;
rwlock_t lock;
#ifdef CONFIG_PROC_FS
struct file_operations fops;
int (* custom_seq_show)(struct seq_file *, void *);
#endif
};
int bt_sock_register(int proto, const struct net_proto_family *ops);
@ -292,6 +297,11 @@ extern void hci_sock_cleanup(void);
extern int bt_sysfs_init(void);
extern void bt_sysfs_cleanup(void);
extern int bt_procfs_init(struct module* module, struct net *net, const char *name,
struct bt_sock_list* sk_list,
int (* seq_show)(struct seq_file *, void *));
extern void bt_procfs_cleanup(struct net *net, const char *name);
extern struct dentry *bt_debugfs;
int l2cap_init(void);

View File

@ -62,6 +62,15 @@
/* First BR/EDR Controller shall have ID = 0 */
#define HCI_BREDR_ID 0
/* AMP controller status */
#define AMP_CTRL_POWERED_DOWN 0x00
#define AMP_CTRL_BLUETOOTH_ONLY 0x01
#define AMP_CTRL_NO_CAPACITY 0x02
#define AMP_CTRL_LOW_CAPACITY 0x03
#define AMP_CTRL_MEDIUM_CAPACITY 0x04
#define AMP_CTRL_HIGH_CAPACITY 0x05
#define AMP_CTRL_FULL_CAPACITY 0x06
/* HCI device quirks */
enum {
HCI_QUIRK_RESET_ON_CLOSE,
@ -1295,6 +1304,8 @@ struct hci_ev_num_comp_blocks {
} __packed;
/* Low energy meta events */
#define LE_CONN_ROLE_MASTER 0x00
#define HCI_EV_LE_CONN_COMPLETE 0x01
struct hci_ev_le_conn_complete {
__u8 status;

View File

@ -115,12 +115,6 @@ struct oob_data {
u8 randomizer[16];
};
struct adv_entry {
struct list_head list;
bdaddr_t bdaddr;
u8 bdaddr_type;
};
struct le_scan_params {
u8 type;
u16 interval;
@ -356,16 +350,16 @@ extern rwlock_t hci_cb_list_lock;
/* ----- HCI interface to upper protocols ----- */
extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
extern int l2cap_disconn_ind(struct hci_conn *hcon);
extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
u16 flags);
extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
/* ----- Inquiry cache ----- */
@ -587,8 +581,7 @@ void hci_conn_put_device(struct hci_conn *conn);
static inline void hci_conn_hold(struct hci_conn *conn)
{
BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt),
atomic_read(&conn->refcnt) + 1);
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
atomic_inc(&conn->refcnt);
cancel_delayed_work(&conn->disc_work);
@ -596,8 +589,7 @@ static inline void hci_conn_hold(struct hci_conn *conn)
static inline void hci_conn_put(struct hci_conn *conn)
{
BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt),
atomic_read(&conn->refcnt) - 1);
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
if (atomic_dec_and_test(&conn->refcnt)) {
unsigned long timeo;
@ -1056,7 +1048,7 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_interleaved_discovery(struct hci_dev *hdev);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
bool mgmt_valid_hdev(struct hci_dev *hdev);
int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);
/* HCI info for socket */

View File

@ -671,20 +671,8 @@ enum {
L2CAP_EV_RECV_FRAME,
};
static inline void l2cap_chan_hold(struct l2cap_chan *c)
{
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
atomic_inc(&c->refcnt);
}
static inline void l2cap_chan_put(struct l2cap_chan *c)
{
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
if (atomic_dec_and_test(&c->refcnt))
kfree(c);
}
void l2cap_chan_hold(struct l2cap_chan *c);
void l2cap_chan_put(struct l2cap_chan *c);
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
{
@ -771,7 +759,6 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
struct l2cap_chan *l2cap_chan_create(void);
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
void l2cap_chan_destroy(struct l2cap_chan *chan);
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
bdaddr_t *dst, u8 dst_type);
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,

View File

@ -108,8 +108,8 @@ struct smp_cmd_security_req {
#define SMP_CONFIRM_FAILED 0x04
#define SMP_PAIRING_NOTSUPP 0x05
#define SMP_ENC_KEY_SIZE 0x06
#define SMP_CMD_NOTSUPP 0x07
#define SMP_UNSPECIFIED 0x08
#define SMP_CMD_NOTSUPP 0x07
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
#define SMP_MIN_ENC_KEY_SIZE 7
@ -123,8 +123,8 @@ struct smp_chan {
struct l2cap_conn *conn;
u8 preq[7]; /* SMP Pairing Request */
u8 prsp[7]; /* SMP Pairing Response */
u8 prnd[16]; /* SMP Pairing Random (local) */
u8 rrnd[16]; /* SMP Pairing Random (remote) */
u8 prnd[16]; /* SMP Pairing Random (local) */
u8 rrnd[16]; /* SMP Pairing Random (remote) */
u8 pcnf[16]; /* SMP Pairing Confirm */
u8 tk[16]; /* SMP Temporary Key */
u8 enc_key_size;

View File

@ -316,7 +316,7 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
BT_DBG("ident %d code %d", hdr->ident, hdr->code);
BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code);
skb_pull(skb, le16_to_cpu(hdr->len));
return 0;
@ -325,17 +325,19 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
/* Handle A2MP signalling */
static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
{
struct a2mp_cmd *hdr = (void *) skb->data;
struct a2mp_cmd *hdr;
struct amp_mgr *mgr = chan->data;
int err = 0;
amp_mgr_get(mgr);
while (skb->len >= sizeof(*hdr)) {
struct a2mp_cmd *hdr = (void *) skb->data;
u16 len = le16_to_cpu(hdr->len);
u16 len;
BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len);
hdr = (void *) skb->data;
len = le16_to_cpu(hdr->len);
BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len);
skb_pull(skb, sizeof(*hdr));
@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
if (err) {
struct a2mp_cmd_rej rej;
rej.reason = __constant_cpu_to_le16(0);
hdr = (void *) skb->data;
BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
@ -412,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
static void a2mp_chan_close_cb(struct l2cap_chan *chan)
{
l2cap_chan_destroy(chan);
l2cap_chan_put(chan);
}
static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state)

View File

@ -28,6 +28,7 @@
#include <asm/ioctls.h>
#include <net/bluetooth/bluetooth.h>
#include <linux/proc_fs.h>
#define VERSION "2.16"
@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
}
EXPORT_SYMBOL(bt_sock_wait_state);
#ifdef CONFIG_PROC_FS
struct bt_seq_state {
struct bt_sock_list *l;
};
static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(seq->private->l->lock)
{
struct bt_seq_state *s = seq->private;
struct bt_sock_list *l = s->l;
read_lock(&l->lock);
return seq_hlist_start_head(&l->head, *pos);
}
static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct bt_seq_state *s = seq->private;
struct bt_sock_list *l = s->l;
return seq_hlist_next(v, &l->head, pos);
}
static void bt_seq_stop(struct seq_file *seq, void *v)
__releases(seq->private->l->lock)
{
struct bt_seq_state *s = seq->private;
struct bt_sock_list *l = s->l;
read_unlock(&l->lock);
}
static int bt_seq_show(struct seq_file *seq, void *v)
{
struct sock *sk;
struct bt_sock *bt;
struct bt_seq_state *s = seq->private;
struct bt_sock_list *l = s->l;
bdaddr_t src_baswapped, dst_baswapped;
if (v == SEQ_START_TOKEN) {
seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
if (l->custom_seq_show) {
seq_putc(seq, ' ');
l->custom_seq_show(seq, v);
}
seq_putc(seq, '\n');
} else {
sk = sk_entry(v);
bt = bt_sk(sk);
baswap(&src_baswapped, &bt->src);
baswap(&dst_baswapped, &bt->dst);
seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
sk,
atomic_read(&sk->sk_refcnt),
sk_rmem_alloc_get(sk),
sk_wmem_alloc_get(sk),
sock_i_uid(sk),
sock_i_ino(sk),
&src_baswapped,
&dst_baswapped,
bt->parent? sock_i_ino(bt->parent): 0LU);
if (l->custom_seq_show) {
seq_putc(seq, ' ');
l->custom_seq_show(seq, v);
}
seq_putc(seq, '\n');
}
return 0;
}
static struct seq_operations bt_seq_ops = {
.start = bt_seq_start,
.next = bt_seq_next,
.stop = bt_seq_stop,
.show = bt_seq_show,
};
static int bt_seq_open(struct inode *inode, struct file *file)
{
struct bt_sock_list *sk_list;
struct bt_seq_state *s;
sk_list = PDE(inode)->data;
s = __seq_open_private(file, &bt_seq_ops,
sizeof(struct bt_seq_state));
if (s == NULL)
return -ENOMEM;
s->l = sk_list;
return 0;
}
int bt_procfs_init(struct module* module, struct net *net, const char *name,
struct bt_sock_list* sk_list,
int (* seq_show)(struct seq_file *, void *))
{
struct proc_dir_entry * pde;
sk_list->custom_seq_show = seq_show;
sk_list->fops.owner = module;
sk_list->fops.open = bt_seq_open;
sk_list->fops.read = seq_read;
sk_list->fops.llseek = seq_lseek;
sk_list->fops.release = seq_release_private;
pde = proc_net_fops_create(net, name, 0, &sk_list->fops);
if (pde == NULL)
return -ENOMEM;
pde->data = sk_list;
return 0;
}
void bt_procfs_cleanup(struct net *net, const char *name)
{
proc_net_remove(net, name);
}
#else
int bt_procfs_init(struct module* module, struct net *net, const char *name,
struct bt_sock_list* sk_list,
int (* seq_show)(struct seq_file *, void *))
{
return 0;
}
void bt_procfs_cleanup(struct net *net, const char *name)
{
}
#endif
EXPORT_SYMBOL(bt_procfs_init);
EXPORT_SYMBOL(bt_procfs_cleanup);
static struct net_proto_family bt_sock_family_ops = {
.owner = THIS_MODULE,
.family = PF_BLUETOOTH,

View File

@ -29,6 +29,10 @@
#include "bnep.h"
static struct bt_sock_list bnep_sk_list = {
.lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
};
static int bnep_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock)
if (!sk)
return 0;
bt_sock_unlink(&bnep_sk_list, sk);
sock_orphan(sk);
sock_put(sk);
return 0;
@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
sk->sk_protocol = protocol;
sk->sk_state = BT_OPEN;
bt_sock_link(&bnep_sk_list, sk);
return 0;
}
@ -222,19 +229,30 @@ int __init bnep_sock_init(void)
return err;
err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
if (err < 0)
if (err < 0) {
BT_ERR("Can't register BNEP socket");
goto error;
}
err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL);
if (err < 0) {
BT_ERR("Failed to create BNEP proc file");
bt_sock_unregister(BTPROTO_BNEP);
goto error;
}
BT_INFO("BNEP socket layer initialized");
return 0;
error:
BT_ERR("Can't register BNEP socket");
proto_unregister(&bnep_proto);
return err;
}
void __exit bnep_sock_cleanup(void)
{
bt_procfs_cleanup(&init_net, "bnep");
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
BT_ERR("Can't unregister BNEP socket");

View File

@ -42,6 +42,10 @@
#include "cmtp.h"
static struct bt_sock_list cmtp_sk_list = {
.lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock)
};
static int cmtp_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock)
if (!sk)
return 0;
bt_sock_unlink(&cmtp_sk_list, sk);
sock_orphan(sk);
sock_put(sk);
@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol,
sk->sk_protocol = protocol;
sk->sk_state = BT_OPEN;
bt_sock_link(&cmtp_sk_list, sk);
return 0;
}
@ -232,19 +240,30 @@ int cmtp_init_sockets(void)
return err;
err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
if (err < 0)
if (err < 0) {
BT_ERR("Can't register CMTP socket");
goto error;
}
err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL);
if (err < 0) {
BT_ERR("Failed to create CMTP proc file");
bt_sock_unregister(BTPROTO_HIDP);
goto error;
}
BT_INFO("CMTP socket layer initialized");
return 0;
error:
BT_ERR("Can't register CMTP socket");
proto_unregister(&cmtp_proto);
return err;
}
void cmtp_cleanup_sockets(void)
{
bt_procfs_cleanup(&init_net, "cmtp");
if (bt_sock_unregister(BTPROTO_CMTP) < 0)
BT_ERR("Can't unregister CMTP socket");

View File

@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev)
hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
if (!test_bit(HCI_SETUP, &hdev->dev_flags)) {
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
mgmt_valid_hdev(hdev)) {
hci_dev_lock(hdev);
mgmt_powered(hdev, 1);
hci_dev_unlock(hdev);
@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
* and no tasks are scheduled. */
hdev->close(hdev);
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
mgmt_valid_hdev(hdev)) {
hci_dev_lock(hdev);
mgmt_powered(hdev, 0);
hci_dev_unlock(hdev);

View File

@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
if (hdev->features[3] & LMP_RSSI_INQ)
events[4] |= 0x02; /* Inquiry Result with RSSI */
if (hdev->features[5] & LMP_SNIFF_SUBR)
if (lmp_sniffsubr_capable(hdev))
events[5] |= 0x20; /* Sniff Subrating */
if (hdev->features[5] & LMP_PAUSE_ENC)
@ -522,13 +522,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
if (hdev->features[6] & LMP_EXT_INQ)
events[5] |= 0x40; /* Extended Inquiry Result */
if (hdev->features[6] & LMP_NO_FLUSH)
if (lmp_no_flush_capable(hdev))
events[7] |= 0x01; /* Enhanced Flush Complete */
if (hdev->features[7] & LMP_LSTO)
events[6] |= 0x80; /* Link Supervision Timeout Changed */
if (hdev->features[6] & LMP_SIMPLE_PAIR) {
if (lmp_ssp_capable(hdev)) {
events[6] |= 0x01; /* IO Capability Request */
events[6] |= 0x02; /* IO Capability Response */
events[6] |= 0x04; /* User Confirmation Request */
@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
* Features Notification */
}
if (hdev->features[4] & LMP_LE)
if (lmp_le_capable(hdev))
events[7] |= 0x20; /* LE Meta-Event */
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
@ -623,11 +623,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
struct hci_cp_write_def_link_policy cp;
u16 link_policy = 0;
if (hdev->features[0] & LMP_RSWITCH)
if (lmp_rswitch_capable(hdev))
link_policy |= HCI_LP_RSWITCH;
if (hdev->features[0] & LMP_HOLD)
link_policy |= HCI_LP_HOLD;
if (hdev->features[0] & LMP_SNIFF)
if (lmp_sniff_capable(hdev))
link_policy |= HCI_LP_SNIFF;
if (hdev->features[1] & LMP_PARK)
link_policy |= HCI_LP_PARK;
@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
hdev->esco_type |= (ESCO_HV3);
}
if (hdev->features[3] & LMP_ESCO)
if (lmp_esco_capable(hdev))
hdev->esco_type |= (ESCO_EV3);
if (hdev->features[4] & LMP_EV4)
@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
break;
}
if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
hci_set_le_support(hdev);
done:
@ -1614,43 +1614,30 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_le_create_conn *cp;
struct hci_conn *conn;
BT_DBG("%s status 0x%2.2x", hdev->name, status);
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
conn);
if (status) {
if (conn && conn->state == BT_CONNECT) {
conn->state = BT_CLOSED;
mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
conn->dst_type, status);
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
}
} else {
if (!conn) {
conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
if (conn) {
conn->dst_type = cp->peer_addr_type;
conn->out = true;
} else {
BT_ERR("No memory for new connection");
}
}
}
hci_dev_lock(hdev);
hci_dev_unlock(hdev);
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
if (!conn) {
hci_dev_unlock(hdev);
return;
}
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
conn);
conn->state = BT_CLOSED;
mgmt_connect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, status);
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
hci_dev_unlock(hdev);
}
}
static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
@ -3252,12 +3239,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev,
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags))
mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
hci_dev_unlock(hdev);
}
static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
@ -3350,11 +3333,23 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev);
if (ev->status) {
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
if (!conn)
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
if (!conn) {
conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
if (!conn) {
BT_ERR("No memory for new connection");
goto unlock;
}
conn->dst_type = ev->bdaddr_type;
if (ev->role == LE_CONN_ROLE_MASTER) {
conn->out = true;
conn->link_mode |= HCI_LM_MASTER;
}
}
if (ev->status) {
mgmt_connect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, ev->status);
hci_proto_connect_cfm(conn, ev->status);
@ -3363,18 +3358,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
goto unlock;
}
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
if (!conn) {
conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
if (!conn) {
BT_ERR("No memory for new connection");
hci_dev_unlock(hdev);
return;
}
conn->dst_type = ev->bdaddr_type;
}
if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
conn->dst_type, 0, NULL, 0, NULL);

View File

@ -1100,21 +1100,30 @@ int __init hci_sock_init(void)
return err;
err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
if (err < 0)
if (err < 0) {
BT_ERR("HCI socket registration failed");
goto error;
}
err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL);
if (err < 0) {
BT_ERR("Failed to create HCI proc file");
bt_sock_unregister(BTPROTO_HCI);
goto error;
}
BT_INFO("HCI socket layer initialized");
return 0;
error:
BT_ERR("HCI socket registration failed");
proto_unregister(&hci_sk_proto);
return err;
}
void hci_sock_cleanup(void)
{
bt_procfs_cleanup(&init_net, "hci");
if (bt_sock_unregister(BTPROTO_HCI) < 0)
BT_ERR("HCI socket unregistration failed");

View File

@ -25,6 +25,10 @@
#include "hidp.h"
static struct bt_sock_list hidp_sk_list = {
.lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock)
};
static int hidp_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock)
if (!sk)
return 0;
bt_sock_unlink(&hidp_sk_list, sk);
sock_orphan(sk);
sock_put(sk);
@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol,
sk->sk_protocol = protocol;
sk->sk_state = BT_OPEN;
bt_sock_link(&hidp_sk_list, sk);
return 0;
}
@ -271,8 +279,19 @@ int __init hidp_init_sockets(void)
return err;
err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops);
if (err < 0)
if (err < 0) {
BT_ERR("Can't register HIDP socket");
goto error;
}
err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL);
if (err < 0) {
BT_ERR("Failed to create HIDP proc file");
bt_sock_unregister(BTPROTO_HIDP);
goto error;
}
BT_INFO("HIDP socket layer initialized");
return 0;
@ -284,6 +303,7 @@ int __init hidp_init_sockets(void)
void __exit hidp_cleanup_sockets(void)
{
bt_procfs_cleanup(&init_net, "hidp");
if (bt_sock_unregister(BTPROTO_HIDP) < 0)
BT_ERR("Can't unregister HIDP socket");

View File

@ -416,13 +416,30 @@ struct l2cap_chan *l2cap_chan_create(void)
return chan;
}
void l2cap_chan_destroy(struct l2cap_chan *chan)
static void l2cap_chan_destroy(struct l2cap_chan *chan)
{
BT_DBG("chan %p", chan);
write_lock(&chan_list_lock);
list_del(&chan->global_l);
write_unlock(&chan_list_lock);
l2cap_chan_put(chan);
kfree(chan);
}
void l2cap_chan_hold(struct l2cap_chan *c)
{
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
atomic_inc(&c->refcnt);
}
void l2cap_chan_put(struct l2cap_chan *c)
{
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
if (atomic_dec_and_test(&c->refcnt))
l2cap_chan_destroy(c);
}
void l2cap_chan_set_defaults(struct l2cap_chan *chan)
@ -5329,7 +5346,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
return exact ? lm1 : lm2;
}
int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
{
struct l2cap_conn *conn;
@ -5342,7 +5359,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
} else
l2cap_conn_del(hcon, bt_to_errno(status));
return 0;
}
int l2cap_disconn_ind(struct hci_conn *hcon)
@ -5356,12 +5372,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
return conn->disc_reason;
}
int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
BT_DBG("hcon %p reason %d", hcon, reason);
l2cap_conn_del(hcon, bt_to_errno(reason));
return 0;
}
static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
@ -5404,6 +5419,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
state_to_string(chan->state));
if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
l2cap_chan_unlock(chan);
continue;
}
if (chan->scid == L2CAP_CID_LE_DATA) {
if (!status && encrypt) {
chan->sec_level = hcon->sec_level;

View File

@ -34,6 +34,10 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/smp.h>
static struct bt_sock_list l2cap_sk_list = {
.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
};
static const struct proto_ops l2cap_sock_ops;
static void l2cap_sock_init(struct sock *sk, struct sock *parent);
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
@ -823,7 +827,7 @@ static void l2cap_sock_kill(struct sock *sk)
/* Kill poor orphan */
l2cap_chan_destroy(l2cap_pi(sk)->chan);
l2cap_chan_put(l2cap_pi(sk)->chan);
sock_set_flag(sk, SOCK_DEAD);
sock_put(sk);
}
@ -886,6 +890,8 @@ static int l2cap_sock_release(struct socket *sock)
if (!sk)
return 0;
bt_sock_unlink(&l2cap_sk_list, sk);
err = l2cap_sock_shutdown(sock, 2);
sock_orphan(sk);
@ -1210,6 +1216,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
return -ENOMEM;
l2cap_sock_init(sk, NULL);
bt_sock_link(&l2cap_sk_list, sk);
return 0;
}
@ -1248,21 +1255,30 @@ int __init l2cap_init_sockets(void)
return err;
err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
if (err < 0)
if (err < 0) {
BT_ERR("L2CAP socket registration failed");
goto error;
}
err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL);
if (err < 0) {
BT_ERR("Failed to create L2CAP proc file");
bt_sock_unregister(BTPROTO_L2CAP);
goto error;
}
BT_INFO("L2CAP socket layer initialized");
return 0;
error:
BT_ERR("L2CAP socket registration failed");
proto_unregister(&l2cap_proto);
return err;
}
void l2cap_cleanup_sockets(void)
{
bt_procfs_cleanup(&init_net, "l2cap");
if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
BT_ERR("L2CAP socket unregistration failed");

View File

@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = {
MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
};
bool mgmt_valid_hdev(struct hci_dev *hdev)
{
return hdev->dev_type == HCI_BREDR;
}
static u8 mgmt_status(u8 hci_status)
{
if (hci_status < ARRAY_SIZE(mgmt_status_table))
@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
struct mgmt_rp_read_index_list *rp;
struct list_head *p;
struct hci_dev *d;
size_t rp_len;
u16 count;
@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
read_lock(&hci_dev_list_lock);
count = 0;
list_for_each(p, &hci_dev_list) {
list_for_each_entry(d, &hci_dev_list, list) {
if (!mgmt_valid_hdev(d))
continue;
count++;
}
@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
if (test_bit(HCI_SETUP, &d->dev_flags))
continue;
if (!mgmt_valid_hdev(d))
continue;
rp->index[i++] = cpu_to_le16(d->id);
BT_DBG("Added hci%u", d->id);
}
@ -370,10 +380,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
settings |= MGMT_SETTING_DISCOVERABLE;
settings |= MGMT_SETTING_PAIRABLE;
if (hdev->features[6] & LMP_SIMPLE_PAIR)
if (lmp_ssp_capable(hdev))
settings |= MGMT_SETTING_SSP;
if (!(hdev->features[4] & LMP_NO_BREDR)) {
if (lmp_bredr_capable(hdev)) {
settings |= MGMT_SETTING_BREDR;
settings |= MGMT_SETTING_LINK_SECURITY;
}
@ -381,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
if (enable_hs)
settings |= MGMT_SETTING_HS;
if (hdev->features[4] & LMP_LE)
if (lmp_le_capable(hdev))
settings |= MGMT_SETTING_LE;
return settings;
@ -403,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
settings |= MGMT_SETTING_PAIRABLE;
if (!(hdev->features[4] & LMP_NO_BREDR))
if (lmp_bredr_capable(hdev))
settings |= MGMT_SETTING_BREDR;
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
@ -1111,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_dev_lock(hdev);
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
if (!lmp_ssp_capable(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_NOT_SUPPORTED);
goto failed;
@ -1195,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_dev_lock(hdev);
if (!(hdev->features[4] & LMP_LE)) {
if (!lmp_le_capable(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_NOT_SUPPORTED);
goto unlock;
@ -2191,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
if (!lmp_ssp_capable(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_NOT_SUPPORTED);
goto unlock;
@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
int mgmt_index_added(struct hci_dev *hdev)
{
if (!mgmt_valid_hdev(hdev))
return -ENOTSUPP;
return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
}
@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev)
{
u8 status = MGMT_STATUS_INVALID_INDEX;
if (!mgmt_valid_hdev(hdev))
return -ENOTSUPP;
mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);

View File

@ -1033,8 +1033,17 @@ int __init rfcomm_init_sockets(void)
return err;
err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops);
if (err < 0)
if (err < 0) {
BT_ERR("RFCOMM socket layer registration failed");
goto error;
}
err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL);
if (err < 0) {
BT_ERR("Failed to create RFCOMM proc file");
bt_sock_unregister(BTPROTO_RFCOMM);
goto error;
}
if (bt_debugfs) {
rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
@ -1048,13 +1057,14 @@ int __init rfcomm_init_sockets(void)
return 0;
error:
BT_ERR("RFCOMM socket layer registration failed");
proto_unregister(&rfcomm_proto);
return err;
}
void __exit rfcomm_cleanup_sockets(void)
{
bt_procfs_cleanup(&init_net, "rfcomm");
debugfs_remove(rfcomm_sock_debugfs);
if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)

View File

@ -913,7 +913,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
return lm;
}
int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
{
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
if (!status) {
@ -924,16 +924,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
sco_conn_ready(conn);
} else
sco_conn_del(hcon, bt_to_errno(status));
return 0;
}
int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
{
BT_DBG("hcon %p reason %d", hcon, reason);
sco_conn_del(hcon, bt_to_errno(reason));
return 0;
}
int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
@ -1026,6 +1023,13 @@ int __init sco_init(void)
goto error;
}
err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL);
if (err < 0) {
BT_ERR("Failed to create SCO proc file");
bt_sock_unregister(BTPROTO_SCO);
goto error;
}
if (bt_debugfs) {
sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
NULL, &sco_debugfs_fops);
@ -1044,6 +1048,8 @@ int __init sco_init(void)
void __exit sco_exit(void)
{
bt_procfs_cleanup(&init_net, "sco");
debugfs_remove(sco_debugfs);
if (bt_sock_unregister(BTPROTO_SCO) < 0)