Loading drivers/bluetooth/btsdio.c +5 −1 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ struct btsdio_data { #define REG_CL_INTRD 0x13 /* Interrupt Clear */ #define REG_CL_INTRD 0x13 /* Interrupt Clear */ #define REG_EN_INTRD 0x14 /* Interrupt Enable */ #define REG_EN_INTRD 0x14 /* Interrupt Enable */ #define REG_MD_STAT 0x20 /* Bluetooth Mode Status */ #define REG_MD_STAT 0x20 /* Bluetooth Mode Status */ #define REG_MD_SET 0x20 /* Bluetooth Mode Set */ static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) { { Loading Loading @@ -212,7 +213,7 @@ static int btsdio_open(struct hci_dev *hdev) } } if (data->func->class == SDIO_CLASS_BT_B) if (data->func->class == SDIO_CLASS_BT_B) sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL); sdio_writeb(data->func, 0x00, REG_MD_SET, NULL); sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); Loading Loading @@ -333,6 +334,9 @@ static int btsdio_probe(struct sdio_func *func, hdev->flush = btsdio_flush; hdev->flush = btsdio_flush; hdev->send = btsdio_send_frame; hdev->send = btsdio_send_frame; if (func->vendor == 0x0104 && func->device == 0x00c5) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); err = hci_register_dev(hdev); err = hci_register_dev(hdev); if (err < 0) { if (err < 0) { hci_free_dev(hdev); hci_free_dev(hdev); Loading drivers/bluetooth/btusb.c +45 −1 Original line number Original line Diff line number Diff line Loading @@ -965,6 +965,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev) return 0; return 0; } } static int btusb_setup_csr(struct hci_dev *hdev) { struct hci_rp_read_local_version *rp; struct sk_buff *skb; int ret; BT_DBG("%s", hdev->name); skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb)); return -PTR_ERR(skb); } rp = (struct hci_rp_read_local_version *) skb->data; if (!rp->status) { if (le16_to_cpu(rp->manufacturer) != 10) { /* Clear the reset quirk since this is not an actual * early Bluetooth 1.1 device from CSR. */ clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); /* These fake CSR controllers have all a broken * stored link key handling and so just disable it. */ set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); } } ret = -bt_to_errno(rp->status); kfree_skb(skb); return ret; } struct intel_version { struct intel_version { u8 status; u8 status; u8 hw_platform; u8 hw_platform; Loading Loading @@ -1465,10 +1504,15 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_CSR) { if (id->driver_info & BTUSB_CSR) { struct usb_device *udev = data->udev; struct usb_device *udev = data->udev; u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice); /* Old firmware would otherwise execute USB reset */ /* Old firmware would otherwise execute USB reset */ if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) if (bcdDevice < 0x117) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); /* Fake CSR devices with broken commands */ if (bcdDevice <= 0x100) hdev->setup = btusb_setup_csr; } } if (id->driver_info & BTUSB_SNIFFER) { if (id->driver_info & BTUSB_SNIFFER) { Loading drivers/bluetooth/hci_vhci.c +18 −11 Original line number Original line Diff line number Diff line Loading @@ -141,23 +141,29 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type) } } static inline ssize_t vhci_get_user(struct vhci_data *data, static inline ssize_t vhci_get_user(struct vhci_data *data, const char __user *buf, size_t count) const struct iovec *iov, unsigned long count) { { size_t len = iov_length(iov, count); struct sk_buff *skb; struct sk_buff *skb; __u8 pkt_type, dev_type; __u8 pkt_type, dev_type; unsigned long i; int ret; int ret; if (count < 2 || count > HCI_MAX_FRAME_SIZE) if (len < 2 || len > HCI_MAX_FRAME_SIZE) return -EINVAL; return -EINVAL; skb = bt_skb_alloc(count, GFP_KERNEL); skb = bt_skb_alloc(len, GFP_KERNEL); if (!skb) if (!skb) return -ENOMEM; return -ENOMEM; if (copy_from_user(skb_put(skb, count), buf, count)) { for (i = 0; i < count; i++) { if (copy_from_user(skb_put(skb, iov[i].iov_len), iov[i].iov_base, iov[i].iov_len)) { kfree_skb(skb); kfree_skb(skb); return -EFAULT; return -EFAULT; } } } pkt_type = *((__u8 *) skb->data); pkt_type = *((__u8 *) skb->data); skb_pull(skb, 1); skb_pull(skb, 1); Loading Loading @@ -205,7 +211,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, return -EINVAL; return -EINVAL; } } return (ret < 0) ? ret : count; return (ret < 0) ? ret : len; } } static inline ssize_t vhci_put_user(struct vhci_data *data, static inline ssize_t vhci_put_user(struct vhci_data *data, Loading Loading @@ -272,12 +278,13 @@ static ssize_t vhci_read(struct file *file, return ret; return ret; } } static ssize_t vhci_write(struct file *file, static ssize_t vhci_write(struct kiocb *iocb, const struct iovec *iov, const char __user *buf, size_t count, loff_t *pos) unsigned long count, loff_t pos) { { struct file *file = iocb->ki_filp; struct vhci_data *data = file->private_data; struct vhci_data *data = file->private_data; return vhci_get_user(data, buf, count); return vhci_get_user(data, iov, count); } } static unsigned int vhci_poll(struct file *file, poll_table *wait) static unsigned int vhci_poll(struct file *file, poll_table *wait) Loading Loading @@ -342,7 +349,7 @@ static int vhci_release(struct inode *inode, struct file *file) static const struct file_operations vhci_fops = { static const struct file_operations vhci_fops = { .owner = THIS_MODULE, .owner = THIS_MODULE, .read = vhci_read, .read = vhci_read, .write = vhci_write, .aio_write = vhci_write, .poll = vhci_poll, .poll = vhci_poll, .open = vhci_open, .open = vhci_open, .release = vhci_release, .release = vhci_release, Loading include/net/bluetooth/hci.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -83,7 +83,8 @@ enum { enum { HCI_QUIRK_RESET_ON_CLOSE, HCI_QUIRK_RESET_ON_CLOSE, HCI_QUIRK_RAW_DEVICE, HCI_QUIRK_RAW_DEVICE, HCI_QUIRK_FIXUP_BUFFER_SIZE HCI_QUIRK_FIXUP_BUFFER_SIZE, HCI_QUIRK_BROKEN_STORED_LINK_KEY, }; }; /* HCI device flags */ /* HCI device flags */ Loading Loading @@ -131,6 +132,7 @@ enum { HCI_PERIODIC_INQ, HCI_PERIODIC_INQ, HCI_FAST_CONNECTABLE, HCI_FAST_CONNECTABLE, HCI_BREDR_ENABLED, HCI_BREDR_ENABLED, HCI_6LOWPAN_ENABLED, }; }; /* A mask for the flags that are supposed to remain when a reset happens /* A mask for the flags that are supposed to remain when a reset happens Loading include/net/bluetooth/hci_core.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -448,6 +448,7 @@ enum { HCI_CONN_SSP_ENABLED, HCI_CONN_SSP_ENABLED, HCI_CONN_POWER_SAVE, HCI_CONN_POWER_SAVE, HCI_CONN_REMOTE_OOB, HCI_CONN_REMOTE_OOB, HCI_CONN_6LOWPAN, }; }; static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) Loading Loading
drivers/bluetooth/btsdio.c +5 −1 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ struct btsdio_data { #define REG_CL_INTRD 0x13 /* Interrupt Clear */ #define REG_CL_INTRD 0x13 /* Interrupt Clear */ #define REG_EN_INTRD 0x14 /* Interrupt Enable */ #define REG_EN_INTRD 0x14 /* Interrupt Enable */ #define REG_MD_STAT 0x20 /* Bluetooth Mode Status */ #define REG_MD_STAT 0x20 /* Bluetooth Mode Status */ #define REG_MD_SET 0x20 /* Bluetooth Mode Set */ static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) { { Loading Loading @@ -212,7 +213,7 @@ static int btsdio_open(struct hci_dev *hdev) } } if (data->func->class == SDIO_CLASS_BT_B) if (data->func->class == SDIO_CLASS_BT_B) sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL); sdio_writeb(data->func, 0x00, REG_MD_SET, NULL); sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); Loading Loading @@ -333,6 +334,9 @@ static int btsdio_probe(struct sdio_func *func, hdev->flush = btsdio_flush; hdev->flush = btsdio_flush; hdev->send = btsdio_send_frame; hdev->send = btsdio_send_frame; if (func->vendor == 0x0104 && func->device == 0x00c5) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); err = hci_register_dev(hdev); err = hci_register_dev(hdev); if (err < 0) { if (err < 0) { hci_free_dev(hdev); hci_free_dev(hdev); Loading
drivers/bluetooth/btusb.c +45 −1 Original line number Original line Diff line number Diff line Loading @@ -965,6 +965,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev) return 0; return 0; } } static int btusb_setup_csr(struct hci_dev *hdev) { struct hci_rp_read_local_version *rp; struct sk_buff *skb; int ret; BT_DBG("%s", hdev->name); skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb)); return -PTR_ERR(skb); } rp = (struct hci_rp_read_local_version *) skb->data; if (!rp->status) { if (le16_to_cpu(rp->manufacturer) != 10) { /* Clear the reset quirk since this is not an actual * early Bluetooth 1.1 device from CSR. */ clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); /* These fake CSR controllers have all a broken * stored link key handling and so just disable it. */ set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); } } ret = -bt_to_errno(rp->status); kfree_skb(skb); return ret; } struct intel_version { struct intel_version { u8 status; u8 status; u8 hw_platform; u8 hw_platform; Loading Loading @@ -1465,10 +1504,15 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_CSR) { if (id->driver_info & BTUSB_CSR) { struct usb_device *udev = data->udev; struct usb_device *udev = data->udev; u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice); /* Old firmware would otherwise execute USB reset */ /* Old firmware would otherwise execute USB reset */ if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) if (bcdDevice < 0x117) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); /* Fake CSR devices with broken commands */ if (bcdDevice <= 0x100) hdev->setup = btusb_setup_csr; } } if (id->driver_info & BTUSB_SNIFFER) { if (id->driver_info & BTUSB_SNIFFER) { Loading
drivers/bluetooth/hci_vhci.c +18 −11 Original line number Original line Diff line number Diff line Loading @@ -141,23 +141,29 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type) } } static inline ssize_t vhci_get_user(struct vhci_data *data, static inline ssize_t vhci_get_user(struct vhci_data *data, const char __user *buf, size_t count) const struct iovec *iov, unsigned long count) { { size_t len = iov_length(iov, count); struct sk_buff *skb; struct sk_buff *skb; __u8 pkt_type, dev_type; __u8 pkt_type, dev_type; unsigned long i; int ret; int ret; if (count < 2 || count > HCI_MAX_FRAME_SIZE) if (len < 2 || len > HCI_MAX_FRAME_SIZE) return -EINVAL; return -EINVAL; skb = bt_skb_alloc(count, GFP_KERNEL); skb = bt_skb_alloc(len, GFP_KERNEL); if (!skb) if (!skb) return -ENOMEM; return -ENOMEM; if (copy_from_user(skb_put(skb, count), buf, count)) { for (i = 0; i < count; i++) { if (copy_from_user(skb_put(skb, iov[i].iov_len), iov[i].iov_base, iov[i].iov_len)) { kfree_skb(skb); kfree_skb(skb); return -EFAULT; return -EFAULT; } } } pkt_type = *((__u8 *) skb->data); pkt_type = *((__u8 *) skb->data); skb_pull(skb, 1); skb_pull(skb, 1); Loading Loading @@ -205,7 +211,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, return -EINVAL; return -EINVAL; } } return (ret < 0) ? ret : count; return (ret < 0) ? ret : len; } } static inline ssize_t vhci_put_user(struct vhci_data *data, static inline ssize_t vhci_put_user(struct vhci_data *data, Loading Loading @@ -272,12 +278,13 @@ static ssize_t vhci_read(struct file *file, return ret; return ret; } } static ssize_t vhci_write(struct file *file, static ssize_t vhci_write(struct kiocb *iocb, const struct iovec *iov, const char __user *buf, size_t count, loff_t *pos) unsigned long count, loff_t pos) { { struct file *file = iocb->ki_filp; struct vhci_data *data = file->private_data; struct vhci_data *data = file->private_data; return vhci_get_user(data, buf, count); return vhci_get_user(data, iov, count); } } static unsigned int vhci_poll(struct file *file, poll_table *wait) static unsigned int vhci_poll(struct file *file, poll_table *wait) Loading Loading @@ -342,7 +349,7 @@ static int vhci_release(struct inode *inode, struct file *file) static const struct file_operations vhci_fops = { static const struct file_operations vhci_fops = { .owner = THIS_MODULE, .owner = THIS_MODULE, .read = vhci_read, .read = vhci_read, .write = vhci_write, .aio_write = vhci_write, .poll = vhci_poll, .poll = vhci_poll, .open = vhci_open, .open = vhci_open, .release = vhci_release, .release = vhci_release, Loading
include/net/bluetooth/hci.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -83,7 +83,8 @@ enum { enum { HCI_QUIRK_RESET_ON_CLOSE, HCI_QUIRK_RESET_ON_CLOSE, HCI_QUIRK_RAW_DEVICE, HCI_QUIRK_RAW_DEVICE, HCI_QUIRK_FIXUP_BUFFER_SIZE HCI_QUIRK_FIXUP_BUFFER_SIZE, HCI_QUIRK_BROKEN_STORED_LINK_KEY, }; }; /* HCI device flags */ /* HCI device flags */ Loading Loading @@ -131,6 +132,7 @@ enum { HCI_PERIODIC_INQ, HCI_PERIODIC_INQ, HCI_FAST_CONNECTABLE, HCI_FAST_CONNECTABLE, HCI_BREDR_ENABLED, HCI_BREDR_ENABLED, HCI_6LOWPAN_ENABLED, }; }; /* A mask for the flags that are supposed to remain when a reset happens /* A mask for the flags that are supposed to remain when a reset happens Loading
include/net/bluetooth/hci_core.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -448,6 +448,7 @@ enum { HCI_CONN_SSP_ENABLED, HCI_CONN_SSP_ENABLED, HCI_CONN_POWER_SAVE, HCI_CONN_POWER_SAVE, HCI_CONN_REMOTE_OOB, HCI_CONN_REMOTE_OOB, HCI_CONN_6LOWPAN, }; }; static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) Loading