Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 300e5fd1 authored by John W. Linville's avatar John W. Linville
Browse files

Merge branch 'for-upstream' of...

parents 6e08d757 e825eb1d
Loading
Loading
Loading
Loading
+5 −1
Original line number Original line Diff line number Diff line
@@ -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)
{
{
@@ -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);


@@ -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);
+45 −1
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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) {
+18 −11
Original line number Original line Diff line number Diff line
@@ -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);
@@ -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,
@@ -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)
@@ -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,
+3 −1
Original line number Original line Diff line number Diff line
@@ -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 */
@@ -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
+1 −0
Original line number Original line Diff line number Diff line
@@ -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