drivers: uart: add system call handlers

Certain interrupt-driven APIs were excluded as they are intended
only to be called from ISRs, or involve registering a callback
which runs in interrupt context.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 4723dad..bb9fcd0 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -20,3 +20,5 @@
 obj-$(CONFIG_UART_ESP32)	+= uart_esp32.o
 obj-$(CONFIG_UART_GECKO)	+= uart_gecko.o
 obj-$(CONFIG_UART_MSP432P4XX)	+= uart_msp432p4xx.o
+
+obj-$(CONFIG_USERSPACE)		+= uart_handlers.o
diff --git a/drivers/serial/uart_handlers.c b/drivers/serial/uart_handlers.c
new file mode 100644
index 0000000..a0f318f
--- /dev/null
+++ b/drivers/serial/uart_handlers.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <uart.h>
+#include <syscall_handler.h>
+
+#define UART_SIMPLE(name_) \
+	_SYSCALL_HANDLER1_SIMPLE(name_, K_OBJ_DRIVER_UART, struct device *)
+
+#define UART_SIMPLE_VOID(name_) \
+	_SYSCALL_HANDLER1_SIMPLE_VOID(name_, K_OBJ_DRIVER_UART, \
+				      struct device *)
+
+UART_SIMPLE(uart_err_check);
+
+_SYSCALL_HANDLER(uart_poll_in, dev, p_char)
+{
+	_SYSCALL_OBJ(dev, K_OBJ_DRIVER_UART);
+	_SYSCALL_MEMORY_WRITE(p_char, sizeof(unsigned char));
+	return _impl_uart_poll_in((struct device *)dev,
+				  (unsigned char *)p_char);
+}
+
+_SYSCALL_HANDLER(uart_poll_out, dev, out_char)
+{
+	_SYSCALL_OBJ(dev, K_OBJ_DRIVER_UART);
+	return _impl_uart_poll_out((struct device *)dev, out_char);
+}
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+UART_SIMPLE_VOID(uart_irq_tx_enable);
+UART_SIMPLE_VOID(uart_irq_tx_disable);
+UART_SIMPLE_VOID(uart_irq_rx_enable);
+UART_SIMPLE_VOID(uart_irq_rx_disable);
+UART_SIMPLE_VOID(uart_irq_err_enable);
+UART_SIMPLE_VOID(uart_irq_err_disable);
+UART_SIMPLE(uart_irq_is_pending);
+UART_SIMPLE(uart_irq_update);
+#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
+
+#ifdef CONFIG_UART_LINE_CTRL
+_SYSCALL_HANDLER(uart_line_ctrl_set, dev, ctrl, val)
+{
+	_SYSCALL_OBJ(dev, K_OBJ_DRIVER_UART);
+	return _impl_uart_line_ctrl_set((struct device *)dev, ctrl, val);
+}
+
+_SYSCALL_HANDLER(uart_line_ctrl_get, dev, ctrl, val);
+{
+	_SYSCALL_OBJ(dev, K_OBJ_DRIVER_UART);
+	_SYSCALL_MEMORY_WRITE(val, sizeof(u32_t));
+	return _impl_uart_line_ctrl_get((struct device *)dev, ctrl,
+					(u32_t *)val);
+}
+#endif /* CONFIG_UART_LINE_CTRL */
+
+#ifdef CONFIG_UART_DRV_CMD
+_SYSCALL_HANDLER(uart_drv_cmd, dev, cmd, p)
+{
+	_SYSCALL_OBJ(dev, K_OBJ_DRIVER_UART);
+	return _impl_uart_drv_cmd((struct device *)dev, cmd, p);
+}
+#endif /* CONFIG_UART_DRV_CMD */
diff --git a/include/uart.h b/include/uart.h
index 5c29e92..4804d30 100644
--- a/include/uart.h
+++ b/include/uart.h
@@ -183,7 +183,9 @@
  * @retval UART_ERROR_BREAK if a break error was detected.
  * @retval 0 Otherwise.
  */
-static inline int uart_err_check(struct device *dev)
+__syscall int uart_err_check(struct device *dev);
+
+static inline int _impl_uart_err_check(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -205,7 +207,9 @@
  *            input buffer was empty).
  * @retval -ENOTSUP If the operation is not supported.
  */
-static inline int uart_poll_in(struct device *dev, unsigned char *p_char)
+__syscall int uart_poll_in(struct device *dev, unsigned char *p_char);
+
+static inline int _impl_uart_poll_in(struct device *dev, unsigned char *p_char)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -227,8 +231,11 @@
  *
  * @retval char Sent character.
  */
-static inline unsigned char uart_poll_out(struct device *dev,
-					  unsigned char out_char)
+__syscall unsigned char uart_poll_out(struct device *dev,
+				      unsigned char out_char);
+
+static inline unsigned char _impl_uart_poll_out(struct device *dev,
+						unsigned char out_char)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -306,7 +313,9 @@
  *
  * @return N/A
  */
-static inline void uart_irq_tx_enable(struct device *dev)
+__syscall void uart_irq_tx_enable(struct device *dev);
+
+static inline void _impl_uart_irq_tx_enable(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -321,7 +330,9 @@
  *
  * @return N/A
  */
-static inline void uart_irq_tx_disable(struct device *dev)
+__syscall void uart_irq_tx_disable(struct device *dev);
+
+static inline void _impl_uart_irq_tx_disable(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -363,7 +374,9 @@
  *
  * @return N/A
  */
-static inline void uart_irq_rx_enable(struct device *dev)
+__syscall void uart_irq_rx_enable(struct device *dev);
+
+static inline void _impl_uart_irq_rx_enable(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -379,7 +392,9 @@
  *
  * @return N/A
  */
-static inline void uart_irq_rx_disable(struct device *dev)
+__syscall void uart_irq_rx_disable(struct device *dev);
+
+static inline void _impl_uart_irq_rx_disable(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -459,7 +474,9 @@
  *
  * @return N/A
  */
-static inline void uart_irq_err_enable(struct device *dev)
+__syscall void uart_irq_err_enable(struct device *dev);
+
+static inline void _impl_uart_irq_err_enable(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -476,7 +493,9 @@
  * @retval 1 If an IRQ is ready.
  * @retval 0 Otherwise.
  */
-static inline void uart_irq_err_disable(struct device *dev)
+__syscall void uart_irq_err_disable(struct device *dev);
+
+static inline void _impl_uart_irq_err_disable(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -493,8 +512,9 @@
  * @retval 1 If an IRQ is pending.
  * @retval 0 Otherwise.
  */
+__syscall int uart_irq_is_pending(struct device *dev);
 
-static inline int uart_irq_is_pending(struct device *dev)
+static inline int _impl_uart_irq_is_pending(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -512,7 +532,9 @@
  *
  * @retval 1 Always.
  */
-static inline int uart_irq_update(struct device *dev)
+__syscall int uart_irq_update(struct device *dev);
+
+static inline int _impl_uart_irq_update(struct device *dev)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -558,8 +580,11 @@
  * @retval 0 If successful.
  * @retval failed Otherwise.
  */
-static inline int uart_line_ctrl_set(struct device *dev,
-				     u32_t ctrl, u32_t val)
+__syscall int uart_line_ctrl_set(struct device *dev,
+				 u32_t ctrl, u32_t val);
+
+static inline int _impl_uart_line_ctrl_set(struct device *dev,
+					   u32_t ctrl, u32_t val)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -580,8 +605,10 @@
  * @retval 0 If successful.
  * @retval failed Otherwise.
  */
-static inline int uart_line_ctrl_get(struct device *dev,
-				     u32_t ctrl, u32_t *val)
+__syscall int uart_line_ctrl_get(struct device *dev, u32_t ctrl, u32_t *val);
+
+static inline int _impl_uart_line_ctrl_get(struct device *dev,
+					   u32_t ctrl, u32_t *val)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -609,7 +636,9 @@
  * @retval 0 If successful.
  * @retval failed Otherwise.
  */
-static inline int uart_drv_cmd(struct device *dev, u32_t cmd, u32_t p)
+__syscall int uart_drv_cmd(struct device *dev, u32_t cmd, u32_t p);
+
+static inline int _impl_uart_drv_cmd(struct device *dev, u32_t cmd, u32_t p)
 {
 	const struct uart_driver_api *api = dev->driver_api;
 
@@ -630,4 +659,6 @@
  * @}
  */
 
+#include <syscalls/uart.h>
+
 #endif /* __INCuarth */