mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-25 00:50:54 +07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
commit
57f784fed3
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user