From afacb1902f682e32c7e9dbf54ccee9c0194b6f2b Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Dec 2025 18:11:23 +0200 Subject: [PATCH 1/7] drivers: dai: fix optional use of dai_get_properties_copy() Handle the case if driver is not implementing get_properties_copy(). Document the behaviour and add a note that the method is optional and users need to be handle the case that not all drivers will have this method defined. Also add documentation on error codes. Drivers should use -ENOENT if no properties are defined for the device. This matches behaviour of dai_get_properties() returning NULL if there are no properties. Signed-off-by: Kai Vehmanen --- include/zephyr/drivers/dai.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/zephyr/drivers/dai.h b/include/zephyr/drivers/dai.h index 606a2f325668..cf37982725fa 100644 --- a/include/zephyr/drivers/dai.h +++ b/include/zephyr/drivers/dai.h @@ -463,12 +463,17 @@ static inline const struct dai_properties *dai_get_properties(const struct devic /** * @brief Fetch properties of a DAI driver * + * Optional method. + * * @param dev Pointer to the device structure for the driver instance * @param dir Stream direction: RX or TX as defined by DAI_DIR_* * @param stream_id Stream id: some drivers may have stream specific * properties, this id specifies the stream. * @param dst address where to write properties to - * @retval Zero on success + * @retval 0 if success + * @retval -EINVAL if arguments are incorrect + * @retval -ENOENT if there are no properties for the device + * @retval -ENOSYS if method not implemented by the driver */ __syscall int dai_get_properties_copy(const struct device *dev, enum dai_dir dir, @@ -482,6 +487,10 @@ static inline int z_impl_dai_get_properties_copy(const struct device *dev, { const struct dai_driver_api *api = (const struct dai_driver_api *)dev->api; + if (!api->get_properties_copy) { + return -ENOSYS; + } + return api->get_properties_copy(dev, dir, stream_id, dst); } From e5e0bf393ab8b11f16a4e240955bfc519afc4187 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Dec 2025 18:16:46 +0200 Subject: [PATCH 2/7] drivers: dai: intel: ssp: fix indentation for dai_ssp_get_properties_copy Fix function indentation to match coding style. Signed-off-by: Kai Vehmanen --- drivers/dai/intel/ssp/ssp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index 653f1d481687..fba24ee2cafb 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -2549,7 +2549,8 @@ static const struct dai_properties *dai_ssp_get_properties(const struct device * } static int dai_ssp_get_properties_copy(const struct device *dev, - enum dai_dir dir, int stream_id, struct dai_properties *prop) + enum dai_dir dir, int stream_id, + struct dai_properties *prop) { const struct dai_properties *kernel_prop = dai_ssp_get_properties(dev, dir, stream_id); From a788cd7f9bfa31c5a5849135c827ad72fd63ea5e Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Dec 2025 18:17:37 +0200 Subject: [PATCH 3/7] drivers: dai: intel: ssp: handle no properties case for properties_copy() dai_ssp_get_properties() can return NULL if there are no properties defined for the device. Handle this case correctly in ssp driver's dai_ssp_get_properties_copy() by returning -ENOENT in this case. Signed-off-by: Kai Vehmanen --- drivers/dai/intel/ssp/ssp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index fba24ee2cafb..a2395a611ac0 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -2558,6 +2558,10 @@ static int dai_ssp_get_properties_copy(const struct device *dev, return -EINVAL; } + if (!kernel_prop) { + return -ENOENT; + } + memcpy(prop, kernel_prop, sizeof(*kernel_prop)); return 0; From c2b3ffd5d8993ec87f1cedb86874ed7dfecf2f34 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Dec 2025 19:57:08 +0200 Subject: [PATCH 4/7] drivers: dai: fix dai_config_set() syscall validation Make a in-kernel copy of 'cfg' parameter before passing the struct to kernel z_impl_dai_config_set() implementation. This ensures user-space will not have access to the object when kernel part of the syscall is running. Also add separate handling for the case where bespoke configuration object is NULL. While no current driver works without a bespoke configuration, this is not forbidden in the API and the generic syscall handler should not assume a bespoke object is passed. Signed-off-by: Kai Vehmanen --- drivers/dai/dai_handlers.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/dai/dai_handlers.c b/drivers/dai/dai_handlers.c index 28283e25a66b..0f4388c94f57 100644 --- a/drivers/dai/dai_handlers.c +++ b/drivers/dai/dai_handlers.c @@ -36,15 +36,21 @@ static inline int z_vrfy_dai_config_set(const struct device *dev, size_t size) { uint8_t bespoke_cfg_kernel[DAI_MAX_BESPOKE_CFG_SIZE]; + struct dai_config cfg_kernel; if (size > DAI_MAX_BESPOKE_CFG_SIZE) { return -EINVAL; } K_OOPS(K_SYSCALL_DRIVER_DAI(dev, config_set)); - K_OOPS(k_usermode_from_copy(bespoke_cfg_kernel, bespoke_cfg, size)); + K_OOPS(k_usermode_from_copy(&cfg_kernel, cfg, sizeof(cfg_kernel))); - return z_impl_dai_config_set(dev, cfg, bespoke_cfg_kernel, size); + if (bespoke_cfg) { + K_OOPS(k_usermode_from_copy(bespoke_cfg_kernel, bespoke_cfg, size)); + } + + return z_impl_dai_config_set(dev, &cfg_kernel, + bespoke_cfg ? bespoke_cfg_kernel : NULL, size); } #include @@ -133,7 +139,7 @@ static inline int z_vrfy_dai_config_update(const struct device *dev, { uint8_t bespoke_cfg_kernel[DAI_MAX_BESPOKE_CFG_SIZE]; - if (size > DAI_MAX_BESPOKE_CFG_SIZE) { + if (!bespoke_cfg || size > DAI_MAX_BESPOKE_CFG_SIZE) { return -EINVAL; } From 3c39214d0987886d160c4ef7ee9040ac8f0856a9 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Dec 2025 20:16:17 +0200 Subject: [PATCH 5/7] drivers: dai: intel: alh: implement get_properties_copy Implement get_properties_copy(). This allows the driver to be used from user-space threads. Signed-off-by: Kai Vehmanen --- drivers/dai/intel/alh/alh.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/dai/intel/alh/alh.c b/drivers/dai/intel/alh/alh.c index 7d8dd0dd14c5..230da39a1ecf 100644 --- a/drivers/dai/intel/alh/alh.c +++ b/drivers/dai/intel/alh/alh.c @@ -158,6 +158,25 @@ static const struct dai_properties *dai_alh_get_properties(const struct device * return prop; } +static int dai_alh_get_properties_copy(const struct device *dev, + enum dai_dir dir, int stream_id, + struct dai_properties *prop) +{ + const struct dai_properties *kernel_prop = dai_alh_get_properties(dev, dir, stream_id); + + if (!prop) { + return -EINVAL; + } + + if (!kernel_prop) { + return -ENOENT; + } + + memcpy(prop, kernel_prop, sizeof(*kernel_prop)); + + return 0; +} + static int dai_alh_probe(const struct device *dev) { k_spinlock_key_t key; @@ -201,6 +220,7 @@ static DEVICE_API(dai, dai_intel_alh_api_funcs) = { .config_get = dai_alh_config_get, .trigger = dai_alh_trigger, .get_properties = dai_alh_get_properties, + .get_properties_copy = dai_alh_get_properties_copy, }; #define DAI_INTEL_ALH_DEVICE_INIT(n) \ From 5036ac6fb529b6bd724e189ca870126c7a15e157 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Dec 2025 20:18:40 +0200 Subject: [PATCH 6/7] drivers: dai: intel: dmic: implement get_properties_copy Implement get_properties_copy(). This allows the driver to be used from user-space threads. Signed-off-by: Kai Vehmanen --- drivers/dai/intel/dmic/dmic.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/dai/intel/dmic/dmic.c b/drivers/dai/intel/dmic/dmic.c index a55a74728ce0..79b71e5d66f8 100644 --- a/drivers/dai/intel/dmic/dmic.c +++ b/drivers/dai/intel/dmic/dmic.c @@ -686,6 +686,25 @@ const struct dai_properties *dai_dmic_get_properties(const struct device *dev, return prop; } +static int dai_dmic_get_properties_copy(const struct device *dev, + enum dai_dir dir, int stream_id, + struct dai_properties *prop) +{ + const struct dai_properties *kernel_prop = dai_dmic_get_properties(dev, dir, stream_id); + + if (!prop) { + return -EINVAL; + } + + if (!kernel_prop) { + return -ENOENT; + } + + memcpy(prop, kernel_prop, sizeof(*kernel_prop)); + + return 0; +} + static int dai_dmic_trigger(const struct device *dev, enum dai_dir dir, enum dai_trigger_cmd cmd) { @@ -857,6 +876,7 @@ DEVICE_API(dai, dai_dmic_ops) = { .config_set = dai_dmic_set_config, .config_get = dai_dmic_get_config, .get_properties = dai_dmic_get_properties, + .get_properties_copy = dai_dmic_get_properties_copy, .trigger = dai_dmic_trigger, .ts_config = dai_dmic_timestamp_config, .ts_start = dai_timestamp_dmic_start, From 3d1d884fa16096a04a54c277d826771262691515 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Dec 2025 20:21:14 +0200 Subject: [PATCH 7/7] drivers: dai: intel: hda: implement get_properties_copy Implement get_properties_copy(). This allows the driver to be used from user-space threads. Signed-off-by: Kai Vehmanen --- drivers/dai/intel/hda/hda.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/dai/intel/hda/hda.c b/drivers/dai/intel/hda/hda.c index c901b20600b0..535fd625d970 100644 --- a/drivers/dai/intel/hda/hda.c +++ b/drivers/dai/intel/hda/hda.c @@ -92,6 +92,25 @@ static const struct dai_properties *dai_hda_get_properties(const struct device * return prop; } +static int dai_hda_get_properties_copy(const struct device *dev, + enum dai_dir dir, int stream_id, + struct dai_properties *prop) +{ + const struct dai_properties *kernel_prop = dai_hda_get_properties(dev, dir, stream_id); + + if (!prop) { + return -EINVAL; + } + + if (!kernel_prop) { + return -ENOENT; + } + + memcpy(prop, kernel_prop, sizeof(*kernel_prop)); + + return 0; +} + static int dai_hda_probe(const struct device *dev) { LOG_DBG("%s", __func__); @@ -139,6 +158,7 @@ static DEVICE_API(dai, dai_intel_hda_api_funcs) = { .config_get = dai_hda_config_get, .trigger = dai_hda_trigger, .get_properties = dai_hda_get_properties, + .get_properties_copy = dai_hda_get_properties_copy, }; #define DAI_INTEL_HDA_DEVICE_INIT(n) \