brintos

brintos / linux-shallow public Read only

0
0
Text · 14.4 KiB · 7651321 Raw
700 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *4 *  Bluetooth virtual HCI driver5 *6 *  Copyright (C) 2000-2001  Qualcomm Incorporated7 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>8 *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>9 */10 11#include <linux/module.h>12#include <linux/unaligned.h>13 14#include <linux/atomic.h>15#include <linux/kernel.h>16#include <linux/init.h>17#include <linux/slab.h>18#include <linux/types.h>19#include <linux/errno.h>20#include <linux/sched.h>21#include <linux/poll.h>22 23#include <linux/skbuff.h>24#include <linux/miscdevice.h>25#include <linux/debugfs.h>26 27#include <net/bluetooth/bluetooth.h>28#include <net/bluetooth/hci_core.h>29 30#define VERSION "1.5"31 32static bool amp;33 34struct vhci_data {35	struct hci_dev *hdev;36 37	wait_queue_head_t read_wait;38	struct sk_buff_head readq;39 40	struct mutex open_mutex;41	struct delayed_work open_timeout;42	struct work_struct suspend_work;43 44	bool suspended;45	bool wakeup;46	__u16 msft_opcode;47	bool aosp_capable;48	atomic_t initialized;49};50 51static int vhci_open_dev(struct hci_dev *hdev)52{53	return 0;54}55 56static int vhci_close_dev(struct hci_dev *hdev)57{58	struct vhci_data *data = hci_get_drvdata(hdev);59 60	skb_queue_purge(&data->readq);61 62	return 0;63}64 65static int vhci_flush(struct hci_dev *hdev)66{67	struct vhci_data *data = hci_get_drvdata(hdev);68 69	skb_queue_purge(&data->readq);70 71	return 0;72}73 74static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)75{76	struct vhci_data *data = hci_get_drvdata(hdev);77 78	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);79 80	skb_queue_tail(&data->readq, skb);81 82	if (atomic_read(&data->initialized))83		wake_up_interruptible(&data->read_wait);84	return 0;85}86 87static int vhci_get_data_path_id(struct hci_dev *hdev, u8 *data_path_id)88{89	*data_path_id = 0;90	return 0;91}92 93static int vhci_get_codec_config_data(struct hci_dev *hdev, __u8 type,94				      struct bt_codec *codec, __u8 *vnd_len,95				      __u8 **vnd_data)96{97	if (type != ESCO_LINK)98		return -EINVAL;99 100	*vnd_len = 0;101	*vnd_data = NULL;102	return 0;103}104 105static bool vhci_wakeup(struct hci_dev *hdev)106{107	struct vhci_data *data = hci_get_drvdata(hdev);108 109	return data->wakeup;110}111 112static ssize_t force_suspend_read(struct file *file, char __user *user_buf,113				  size_t count, loff_t *ppos)114{115	struct vhci_data *data = file->private_data;116	char buf[3];117 118	buf[0] = data->suspended ? 'Y' : 'N';119	buf[1] = '\n';120	buf[2] = '\0';121	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);122}123 124static void vhci_suspend_work(struct work_struct *work)125{126	struct vhci_data *data = container_of(work, struct vhci_data,127					      suspend_work);128 129	if (data->suspended)130		hci_suspend_dev(data->hdev);131	else132		hci_resume_dev(data->hdev);133}134 135static ssize_t force_suspend_write(struct file *file,136				   const char __user *user_buf,137				   size_t count, loff_t *ppos)138{139	struct vhci_data *data = file->private_data;140	bool enable;141	int err;142 143	err = kstrtobool_from_user(user_buf, count, &enable);144	if (err)145		return err;146 147	if (data->suspended == enable)148		return -EALREADY;149 150	data->suspended = enable;151 152	schedule_work(&data->suspend_work);153 154	return count;155}156 157static const struct file_operations force_suspend_fops = {158	.open		= simple_open,159	.read		= force_suspend_read,160	.write		= force_suspend_write,161	.llseek		= default_llseek,162};163 164static ssize_t force_wakeup_read(struct file *file, char __user *user_buf,165				 size_t count, loff_t *ppos)166{167	struct vhci_data *data = file->private_data;168	char buf[3];169 170	buf[0] = data->wakeup ? 'Y' : 'N';171	buf[1] = '\n';172	buf[2] = '\0';173	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);174}175 176static ssize_t force_wakeup_write(struct file *file,177				  const char __user *user_buf, size_t count,178				  loff_t *ppos)179{180	struct vhci_data *data = file->private_data;181	bool enable;182	int err;183 184	err = kstrtobool_from_user(user_buf, count, &enable);185	if (err)186		return err;187 188	if (data->wakeup == enable)189		return -EALREADY;190 191	data->wakeup = enable;192 193	return count;194}195 196static const struct file_operations force_wakeup_fops = {197	.open		= simple_open,198	.read		= force_wakeup_read,199	.write		= force_wakeup_write,200	.llseek		= default_llseek,201};202 203static int msft_opcode_set(void *data, u64 val)204{205	struct vhci_data *vhci = data;206 207	if (val > 0xffff || hci_opcode_ogf(val) != 0x3f)208		return -EINVAL;209 210	if (vhci->msft_opcode)211		return -EALREADY;212 213	vhci->msft_opcode = val;214 215	return 0;216}217 218static int msft_opcode_get(void *data, u64 *val)219{220	struct vhci_data *vhci = data;221 222	*val = vhci->msft_opcode;223 224	return 0;225}226 227DEFINE_DEBUGFS_ATTRIBUTE(msft_opcode_fops, msft_opcode_get, msft_opcode_set,228			 "%llu\n");229 230static ssize_t aosp_capable_read(struct file *file, char __user *user_buf,231				 size_t count, loff_t *ppos)232{233	struct vhci_data *vhci = file->private_data;234	char buf[3];235 236	buf[0] = vhci->aosp_capable ? 'Y' : 'N';237	buf[1] = '\n';238	buf[2] = '\0';239	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);240}241 242static ssize_t aosp_capable_write(struct file *file,243				  const char __user *user_buf, size_t count,244				  loff_t *ppos)245{246	struct vhci_data *vhci = file->private_data;247	bool enable;248	int err;249 250	err = kstrtobool_from_user(user_buf, count, &enable);251	if (err)252		return err;253 254	if (!enable)255		return -EINVAL;256 257	if (vhci->aosp_capable)258		return -EALREADY;259 260	vhci->aosp_capable = enable;261 262	return count;263}264 265static const struct file_operations aosp_capable_fops = {266	.open		= simple_open,267	.read		= aosp_capable_read,268	.write		= aosp_capable_write,269	.llseek		= default_llseek,270};271 272static int vhci_setup(struct hci_dev *hdev)273{274	struct vhci_data *vhci = hci_get_drvdata(hdev);275 276	if (vhci->msft_opcode)277		hci_set_msft_opcode(hdev, vhci->msft_opcode);278 279	if (vhci->aosp_capable)280		hci_set_aosp_capable(hdev);281 282	return 0;283}284 285static void vhci_coredump(struct hci_dev *hdev)286{287	/* No need to do anything */288}289 290static void vhci_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)291{292	char buf[80];293 294	snprintf(buf, sizeof(buf), "Controller Name: vhci_ctrl\n");295	skb_put_data(skb, buf, strlen(buf));296 297	snprintf(buf, sizeof(buf), "Firmware Version: vhci_fw\n");298	skb_put_data(skb, buf, strlen(buf));299 300	snprintf(buf, sizeof(buf), "Driver: vhci_drv\n");301	skb_put_data(skb, buf, strlen(buf));302 303	snprintf(buf, sizeof(buf), "Vendor: vhci\n");304	skb_put_data(skb, buf, strlen(buf));305}306 307#define MAX_COREDUMP_LINE_LEN	40308 309struct devcoredump_test_data {310	enum devcoredump_state state;311	unsigned int timeout;312	char data[MAX_COREDUMP_LINE_LEN];313};314 315static inline void force_devcd_timeout(struct hci_dev *hdev,316				       unsigned int timeout)317{318#ifdef CONFIG_DEV_COREDUMP319	hdev->dump.timeout = msecs_to_jiffies(timeout * 1000);320#endif321}322 323static ssize_t force_devcd_write(struct file *file, const char __user *user_buf,324				 size_t count, loff_t *ppos)325{326	struct vhci_data *data = file->private_data;327	struct hci_dev *hdev = data->hdev;328	struct sk_buff *skb = NULL;329	struct devcoredump_test_data dump_data;330	size_t data_size;331	int ret;332 333	if (count < offsetof(struct devcoredump_test_data, data) ||334	    count > sizeof(dump_data))335		return -EINVAL;336 337	if (copy_from_user(&dump_data, user_buf, count))338		return -EFAULT;339 340	data_size = count - offsetof(struct devcoredump_test_data, data);341	skb = alloc_skb(data_size, GFP_ATOMIC);342	if (!skb)343		return -ENOMEM;344	skb_put_data(skb, &dump_data.data, data_size);345 346	hci_devcd_register(hdev, vhci_coredump, vhci_coredump_hdr, NULL);347 348	/* Force the devcoredump timeout */349	if (dump_data.timeout)350		force_devcd_timeout(hdev, dump_data.timeout);351 352	ret = hci_devcd_init(hdev, skb->len);353	if (ret) {354		BT_ERR("Failed to generate devcoredump");355		kfree_skb(skb);356		return ret;357	}358 359	hci_devcd_append(hdev, skb);360 361	switch (dump_data.state) {362	case HCI_DEVCOREDUMP_DONE:363		hci_devcd_complete(hdev);364		break;365	case HCI_DEVCOREDUMP_ABORT:366		hci_devcd_abort(hdev);367		break;368	case HCI_DEVCOREDUMP_TIMEOUT:369		/* Do nothing */370		break;371	default:372		return -EINVAL;373	}374 375	return count;376}377 378static const struct file_operations force_devcoredump_fops = {379	.open		= simple_open,380	.write		= force_devcd_write,381};382 383static int __vhci_create_device(struct vhci_data *data, __u8 opcode)384{385	struct hci_dev *hdev;386	struct sk_buff *skb;387 388	if (data->hdev)389		return -EBADFD;390 391	/* bits 2-5 are reserved (must be zero) */392	if (opcode & 0x3c)393		return -EINVAL;394 395	skb = bt_skb_alloc(4, GFP_KERNEL);396	if (!skb)397		return -ENOMEM;398 399	hdev = hci_alloc_dev();400	if (!hdev) {401		kfree_skb(skb);402		return -ENOMEM;403	}404 405	data->hdev = hdev;406 407	hdev->bus = HCI_VIRTUAL;408	hci_set_drvdata(hdev, data);409 410	hdev->open  = vhci_open_dev;411	hdev->close = vhci_close_dev;412	hdev->flush = vhci_flush;413	hdev->send  = vhci_send_frame;414	hdev->get_data_path_id = vhci_get_data_path_id;415	hdev->get_codec_config_data = vhci_get_codec_config_data;416	hdev->wakeup = vhci_wakeup;417	hdev->setup = vhci_setup;418	set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);419 420	/* bit 6 is for external configuration */421	if (opcode & 0x40)422		set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);423 424	/* bit 7 is for raw device */425	if (opcode & 0x80)426		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);427 428	if (hci_register_dev(hdev) < 0) {429		BT_ERR("Can't register HCI device");430		hci_free_dev(hdev);431		data->hdev = NULL;432		kfree_skb(skb);433		return -EBUSY;434	}435 436	debugfs_create_file("force_suspend", 0644, hdev->debugfs, data,437			    &force_suspend_fops);438 439	debugfs_create_file("force_wakeup", 0644, hdev->debugfs, data,440			    &force_wakeup_fops);441 442	if (IS_ENABLED(CONFIG_BT_MSFTEXT))443		debugfs_create_file("msft_opcode", 0644, hdev->debugfs, data,444				    &msft_opcode_fops);445 446	if (IS_ENABLED(CONFIG_BT_AOSPEXT))447		debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data,448				    &aosp_capable_fops);449 450	debugfs_create_file("force_devcoredump", 0644, hdev->debugfs, data,451			    &force_devcoredump_fops);452 453	hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;454 455	skb_put_u8(skb, 0xff);456	skb_put_u8(skb, opcode);457	put_unaligned_le16(hdev->id, skb_put(skb, 2));458	skb_queue_head(&data->readq, skb);459	atomic_inc(&data->initialized);460 461	wake_up_interruptible(&data->read_wait);462	return 0;463}464 465static int vhci_create_device(struct vhci_data *data, __u8 opcode)466{467	int err;468 469	mutex_lock(&data->open_mutex);470	err = __vhci_create_device(data, opcode);471	mutex_unlock(&data->open_mutex);472 473	return err;474}475 476static inline ssize_t vhci_get_user(struct vhci_data *data,477				    struct iov_iter *from)478{479	size_t len = iov_iter_count(from);480	struct sk_buff *skb;481	__u8 pkt_type, opcode;482	int ret;483 484	if (len < 2 || len > HCI_MAX_FRAME_SIZE)485		return -EINVAL;486 487	skb = bt_skb_alloc(len, GFP_KERNEL);488	if (!skb)489		return -ENOMEM;490 491	if (!copy_from_iter_full(skb_put(skb, len), len, from)) {492		kfree_skb(skb);493		return -EFAULT;494	}495 496	pkt_type = *((__u8 *) skb->data);497	skb_pull(skb, 1);498 499	switch (pkt_type) {500	case HCI_EVENT_PKT:501	case HCI_ACLDATA_PKT:502	case HCI_SCODATA_PKT:503	case HCI_ISODATA_PKT:504		if (!data->hdev) {505			kfree_skb(skb);506			return -ENODEV;507		}508 509		hci_skb_pkt_type(skb) = pkt_type;510 511		ret = hci_recv_frame(data->hdev, skb);512		break;513 514	case HCI_VENDOR_PKT:515		cancel_delayed_work_sync(&data->open_timeout);516 517		opcode = *((__u8 *) skb->data);518		skb_pull(skb, 1);519 520		if (skb->len > 0) {521			kfree_skb(skb);522			return -EINVAL;523		}524 525		kfree_skb(skb);526 527		ret = vhci_create_device(data, opcode);528		break;529 530	default:531		kfree_skb(skb);532		return -EINVAL;533	}534 535	return (ret < 0) ? ret : len;536}537 538static inline ssize_t vhci_put_user(struct vhci_data *data,539				    struct sk_buff *skb,540				    char __user *buf, int count)541{542	char __user *ptr = buf;543	int len;544 545	len = min_t(unsigned int, skb->len, count);546 547	if (copy_to_user(ptr, skb->data, len))548		return -EFAULT;549 550	if (!data->hdev)551		return len;552 553	data->hdev->stat.byte_tx += len;554 555	switch (hci_skb_pkt_type(skb)) {556	case HCI_COMMAND_PKT:557		data->hdev->stat.cmd_tx++;558		break;559	case HCI_ACLDATA_PKT:560		data->hdev->stat.acl_tx++;561		break;562	case HCI_SCODATA_PKT:563		data->hdev->stat.sco_tx++;564		break;565	}566 567	return len;568}569 570static ssize_t vhci_read(struct file *file,571			 char __user *buf, size_t count, loff_t *pos)572{573	struct vhci_data *data = file->private_data;574	struct sk_buff *skb;575	ssize_t ret = 0;576 577	while (count) {578		skb = skb_dequeue(&data->readq);579		if (skb) {580			ret = vhci_put_user(data, skb, buf, count);581			if (ret < 0)582				skb_queue_head(&data->readq, skb);583			else584				kfree_skb(skb);585			break;586		}587 588		if (file->f_flags & O_NONBLOCK) {589			ret = -EAGAIN;590			break;591		}592 593		ret = wait_event_interruptible(data->read_wait,594					       !skb_queue_empty(&data->readq));595		if (ret < 0)596			break;597	}598 599	return ret;600}601 602static ssize_t vhci_write(struct kiocb *iocb, struct iov_iter *from)603{604	struct file *file = iocb->ki_filp;605	struct vhci_data *data = file->private_data;606 607	return vhci_get_user(data, from);608}609 610static __poll_t vhci_poll(struct file *file, poll_table *wait)611{612	struct vhci_data *data = file->private_data;613 614	poll_wait(file, &data->read_wait, wait);615 616	if (!skb_queue_empty(&data->readq))617		return EPOLLIN | EPOLLRDNORM;618 619	return EPOLLOUT | EPOLLWRNORM;620}621 622static void vhci_open_timeout(struct work_struct *work)623{624	struct vhci_data *data = container_of(work, struct vhci_data,625					      open_timeout.work);626 627	vhci_create_device(data, 0x00);628}629 630static int vhci_open(struct inode *inode, struct file *file)631{632	struct vhci_data *data;633 634	data = kzalloc(sizeof(*data), GFP_KERNEL);635	if (!data)636		return -ENOMEM;637 638	skb_queue_head_init(&data->readq);639	init_waitqueue_head(&data->read_wait);640 641	mutex_init(&data->open_mutex);642	INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);643	INIT_WORK(&data->suspend_work, vhci_suspend_work);644 645	file->private_data = data;646	nonseekable_open(inode, file);647 648	schedule_delayed_work(&data->open_timeout, msecs_to_jiffies(1000));649 650	return 0;651}652 653static int vhci_release(struct inode *inode, struct file *file)654{655	struct vhci_data *data = file->private_data;656	struct hci_dev *hdev;657 658	cancel_delayed_work_sync(&data->open_timeout);659	flush_work(&data->suspend_work);660 661	hdev = data->hdev;662 663	if (hdev) {664		hci_unregister_dev(hdev);665		hci_free_dev(hdev);666	}667 668	skb_queue_purge(&data->readq);669	file->private_data = NULL;670	kfree(data);671 672	return 0;673}674 675static const struct file_operations vhci_fops = {676	.owner		= THIS_MODULE,677	.read		= vhci_read,678	.write_iter	= vhci_write,679	.poll		= vhci_poll,680	.open		= vhci_open,681	.release	= vhci_release,682};683 684static struct miscdevice vhci_miscdev = {685	.name	= "vhci",686	.fops	= &vhci_fops,687	.minor	= VHCI_MINOR,688};689module_misc_device(vhci_miscdev);690 691module_param(amp, bool, 0644);692MODULE_PARM_DESC(amp, "Create AMP controller device");693 694MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");695MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);696MODULE_VERSION(VERSION);697MODULE_LICENSE("GPL");698MODULE_ALIAS("devname:vhci");699MODULE_ALIAS_MISCDEV(VHCI_MINOR);700