1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/internal/syscall_handler.h>
9 #include <zephyr/drivers/i2s.h>
10 
11 
z_vrfy_i2s_configure(const struct device * dev,enum i2s_dir dir,const struct i2s_config * cfg_ptr)12 static inline int z_vrfy_i2s_configure(const struct device *dev,
13 				       enum i2s_dir dir,
14 				       const struct i2s_config *cfg_ptr)
15 {
16 	struct i2s_config config;
17 	int ret = -EINVAL;
18 
19 	if (K_SYSCALL_DRIVER_I2S(dev, configure)) {
20 		goto out;
21 	}
22 
23 	K_OOPS(k_usermode_from_copy(&config, (const void *)cfg_ptr,
24 				sizeof(struct i2s_config)));
25 
26 	/* Check that the k_mem_slab provided is a valid pointer and that
27 	 * the caller has permission on it
28 	 */
29 	if (K_SYSCALL_OBJ(config.mem_slab, K_OBJ_MEM_SLAB)) {
30 		goto out;
31 	}
32 
33 	/* Ensure that the k_mem_slab's slabs are large enough for the
34 	 * specified block size
35 	 */
36 	if (config.block_size > config.mem_slab->info.block_size) {
37 		goto out;
38 	}
39 
40 	ret = z_impl_i2s_configure((const struct device *)dev, dir, &config);
41 out:
42 	return ret;
43 }
44 #include <zephyr/syscalls/i2s_configure_mrsh.c>
45 
z_vrfy_i2s_buf_read(const struct device * dev,void * buf,size_t * size)46 static inline int z_vrfy_i2s_buf_read(const struct device *dev,
47 				      void *buf, size_t *size)
48 {
49 	void *mem_block;
50 	size_t data_size;
51 	int ret;
52 
53 	K_OOPS(K_SYSCALL_DRIVER_I2S(dev, read));
54 
55 	ret = i2s_read((const struct device *)dev, &mem_block, &data_size);
56 
57 	if (!ret) {
58 		const struct i2s_config *rx_cfg;
59 		int copy_success;
60 
61 		/* Presumed to be configured otherwise the i2s_read() call
62 		 * would have failed.
63 		 */
64 		rx_cfg = i2s_config_get((const struct device *)dev, I2S_DIR_RX);
65 
66 		copy_success = k_usermode_to_copy((void *)buf, mem_block,
67 					      data_size);
68 
69 		k_mem_slab_free(rx_cfg->mem_slab, mem_block);
70 		K_OOPS(copy_success);
71 		K_OOPS(k_usermode_to_copy((void *)size, &data_size,
72 				      sizeof(data_size)));
73 	}
74 
75 	return ret;
76 }
77 #include <zephyr/syscalls/i2s_buf_read_mrsh.c>
78 
z_vrfy_i2s_buf_write(const struct device * dev,void * buf,size_t size)79 static inline int z_vrfy_i2s_buf_write(const struct device *dev,
80 				       void *buf, size_t size)
81 {
82 	int ret;
83 	const struct i2s_config *tx_cfg;
84 	void *mem_block;
85 
86 	K_OOPS(K_SYSCALL_DRIVER_I2S(dev, write));
87 	tx_cfg = i2s_config_get((const struct device *)dev, I2S_DIR_TX);
88 	if (!tx_cfg) {
89 		return -EIO;
90 	}
91 
92 	if (size > tx_cfg->block_size) {
93 		return -EINVAL;
94 	}
95 
96 	ret = k_mem_slab_alloc(tx_cfg->mem_slab, &mem_block, K_FOREVER);
97 	if (ret < 0) {
98 		return -ENOMEM;
99 	}
100 
101 	ret = k_usermode_from_copy(mem_block, (void *)buf, size);
102 	if (ret) {
103 		k_mem_slab_free(tx_cfg->mem_slab, mem_block);
104 		K_OOPS(ret);
105 	}
106 
107 	ret = i2s_write((const struct device *)dev, mem_block, size);
108 	if (ret != 0) {
109 		k_mem_slab_free(tx_cfg->mem_slab, mem_block);
110 	}
111 
112 	return ret;
113 }
114 #include <zephyr/syscalls/i2s_buf_write_mrsh.c>
115 
z_vrfy_i2s_trigger(const struct device * dev,enum i2s_dir dir,enum i2s_trigger_cmd cmd)116 static inline int z_vrfy_i2s_trigger(const struct device *dev,
117 				     enum i2s_dir dir,
118 				     enum i2s_trigger_cmd cmd)
119 {
120 	K_OOPS(K_SYSCALL_DRIVER_I2S(dev, trigger));
121 
122 	return z_impl_i2s_trigger((const struct device *)dev, dir, cmd);
123 }
124 #include <zephyr/syscalls/i2s_trigger_mrsh.c>
125