linux/sound/soc/sof/sof-client-ipc-msg-injector.c

// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2022 Intel Corporation
//
// Author: Peter Ujfalusi <[email protected]>
//

#include <linux/auxiliary_bus.h>
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/ktime.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <sound/sof/header.h>
#include <sound/sof/ipc4/header.h>

#include "sof-client.h"

#define SOF_IPC_CLIENT_SUSPEND_DELAY_MS

struct sof_msg_inject_priv {};

static int sof_msg_inject_dfs_open(struct inode *inode, struct file *file)
{}

static ssize_t sof_msg_inject_dfs_read(struct file *file, char __user *buffer,
				       size_t count, loff_t *ppos)
{}

static ssize_t sof_msg_inject_ipc4_dfs_read(struct file *file,
					    char __user *buffer,
					    size_t count, loff_t *ppos)
{}

static int sof_msg_inject_send_message(struct sof_client_dev *cdev)
{}

static ssize_t sof_msg_inject_dfs_write(struct file *file, const char __user *buffer,
					size_t count, loff_t *ppos)
{
	struct sof_client_dev *cdev = file->private_data;
	struct sof_msg_inject_priv *priv = cdev->data;
	ssize_t size;
	int ret;

	if (*ppos)
		return 0;

	size = simple_write_to_buffer(priv->tx_buffer, priv->max_msg_size,
				      ppos, buffer, count);
	if (size < 0)
		return size;
	if (size != count)
		return -EFAULT;

	memset(priv->rx_buffer, 0, priv->max_msg_size);

	ret = sof_msg_inject_send_message(cdev);

	/* return the error code if test failed */
	if (ret < 0)
		size = ret;

	return size;
};

static ssize_t sof_msg_inject_ipc4_dfs_write(struct file *file,
					     const char __user *buffer,
					     size_t count, loff_t *ppos)
{
	struct sof_client_dev *cdev = file->private_data;
	struct sof_msg_inject_priv *priv = cdev->data;
	struct sof_ipc4_msg *ipc4_msg = priv->tx_buffer;
	size_t data_size;
	int ret;

	if (*ppos)
		return 0;

	if (count < sizeof(ipc4_msg->header_u64))
		return -EINVAL;

	/* copy the header first */
	if (copy_from_user(&ipc4_msg->header_u64, buffer,
			   sizeof(ipc4_msg->header_u64)))
		return -EFAULT;

	data_size = count - sizeof(ipc4_msg->header_u64);
	if (data_size > priv->max_msg_size)
		return -EINVAL;

	/* Copy the payload */
	if (copy_from_user(ipc4_msg->data_ptr,
			   buffer + sizeof(ipc4_msg->header_u64), data_size))
		return -EFAULT;

	ipc4_msg->data_size = data_size;

	/* Initialize the reply storage */
	ipc4_msg = priv->rx_buffer;
	ipc4_msg->header_u64 = 0;
	ipc4_msg->data_size = priv->max_msg_size;
	memset(ipc4_msg->data_ptr, 0, priv->max_msg_size);

	ret = sof_msg_inject_send_message(cdev);

	/* return the error code if test failed */
	if (ret < 0)
		return ret;

	return count;
};

static int sof_msg_inject_dfs_release(struct inode *inode, struct file *file)
{}

static const struct file_operations sof_msg_inject_fops =;

static const struct file_operations sof_msg_inject_ipc4_fops =;

static int sof_msg_inject_probe(struct auxiliary_device *auxdev,
				const struct auxiliary_device_id *id)
{}

static void sof_msg_inject_remove(struct auxiliary_device *auxdev)
{}

static const struct auxiliary_device_id sof_msg_inject_client_id_table[] =;
MODULE_DEVICE_TABLE(auxiliary, sof_msg_inject_client_id_table);

/*
 * No need for driver pm_ops as the generic pm callbacks in the auxiliary bus
 * type are enough to ensure that the parent SOF device resumes to bring the DSP
 * back to D0.
 * Driver name will be set based on KBUILD_MODNAME.
 */
static struct auxiliary_driver sof_msg_inject_client_drv =;

module_auxiliary_driver();

MODULE_LICENSE();
MODULE_DESCRIPTION();
MODULE_IMPORT_NS();