zephyr/drivers/spi/spi_handlers.c
Andrew Boie 0cb0447493 drivers: spi: add system call handlers
spi_transceive_async() omitted as we don't support k_poll objects
in user mode (yet).

The checking for spi_transceive() is fairly complex as we have to
validate the config struct passed in along with device instances
contained within it.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-10-30 13:20:19 -07:00

67 lines
1.6 KiB
C

/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <spi.h>
#include <syscall_handler.h>
#ifndef CONFIG_SPI_LEGACY_API
static void verify_spi_buf_array(struct spi_buf *bufs, size_t len,
int writable, void *ssf)
{
/* Empty array, nothing to do */
if (!len) {
return;
}
/* Validate the array of struct spi_buf instances */
_SYSCALL_MEMORY_ARRAY_READ(bufs, len, sizeof(struct spi_buf));
for ( ; len; --len, ++bufs) {
/* Now for each array element, validate the memory buffers
* that they point to
*/
_SYSCALL_MEMORY(bufs->buf, bufs->len, writable);
}
}
_SYSCALL_HANDLER(spi_transceive, config_p, tx_bufs, tx_count, rx_bufs,
rx_count)
{
struct spi_config *config = (struct spi_config *)config_p;
_SYSCALL_MEMORY_READ(config, sizeof(*config));
_SYSCALL_OBJ(config->dev, K_OBJ_DRIVER_SPI);
/* ssf is implicit system call stack frame parameter, used by
* _SYSCALL_* APIs when something goes wrong.
*/
verify_spi_buf_array((struct spi_buf *)tx_bufs, tx_count, 0, ssf);
verify_spi_buf_array((struct spi_buf *)rx_bufs, rx_count, 1, ssf);
if (config->cs) {
struct spi_cs_control *cs = config->cs;
_SYSCALL_MEMORY_READ(cs, sizeof(*cs));
if (cs->gpio_dev) {
_SYSCALL_OBJ(cs->gpio_dev, K_OBJ_DRIVER_GPIO);
}
}
return _impl_spi_transceive(config, (const struct spi_buf *)tx_bufs,
tx_count, (struct spi_buf *)rx_bufs,
rx_count);
}
_SYSCALL_HANDLER(spi_release, config_p)
{
struct spi_config *config = (struct spi_config *)config_p;
_SYSCALL_MEMORY_READ(config, sizeof(*config));
_SYSCALL_OBJ(config->dev, K_OBJ_DRIVER_SPI);
return _impl_spi_release(config);
}
#endif