uart: Add nonblocking IO and assorted functions 14/286314/3
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Mon, 2 Jan 2023 16:23:55 +0000 (17:23 +0100)
committerMichal Bloch <m.bloch@samsung.com>
Mon, 13 Feb 2023 11:49:58 +0000 (12:49 +0100)
This commits extends UART API with following:

 * additional nonblocking variants of the peripheral_open_flags_e for use
   in peripheral_open_with_flags():
   - PERIPHERAL_OPEN_FLAGS_PRIVATE_NONBLOCK
   - PERIPHERAL_OPEN_FLAGS_SHARED_NONBLOCK

 * peripheral_uart_drain() and peripheral_uart_flush() API functions

Change-Id: I4fe45ff8a2115e954244affe16818aa5b9710e47

include/peripheral_io.h
packaging/capi-system-peripheral-io.spec
src/common.h
src/peripheral_uart.c

index c438a23a54509f79592d6adacc7fbc035386a1ac..e90b0f381dff789e24cbd94fbf14e00e70424cfa 100644 (file)
@@ -342,12 +342,19 @@ typedef struct _peripheral_i2c_s *peripheral_i2c_h;
 int peripheral_i2c_open(int bus, int address, peripheral_i2c_h *i2c);
 
 /**
- * @brief Enumeration for open flags.
+ * @brief Enumeration for open flags (bitmask).
  * @since_tizen 6.5
+ *
+ * @remarks Enum values are supposed to be used as bitmask, where only one
+ * value can be specified for following flag groups:
+ * - locking mode - either #PERIPHERAL_OPEN_FLAGS_PRIVATE or #PERIPHERAL_OPEN_FLAGS_SHARED can be used
+ *
+ * The #PERIPHERAL_OPEN_FLAGS_NONBLOCK can be used with all other available flags.
  */
 typedef enum {
-       PERIPHERAL_OPEN_FLAGS_PRIVATE = 0, /**< Exclusive access to device */
-       PERIPHERAL_OPEN_FLAGS_SHARED  = 1, /**< Shared access to device */
+       PERIPHERAL_OPEN_FLAGS_PRIVATE = 0,          /**< Exclusive access to device */
+       PERIPHERAL_OPEN_FLAGS_SHARED  = 1,          /**< Shared access to device */
+       PERIPHERAL_OPEN_FLAGS_NONBLOCK = 2,         /**< (Since 7.5) Nonblocking read/write flag */
 } peripheral_open_flags_e;
 
 /**
@@ -1086,6 +1093,49 @@ int peripheral_uart_set_flow_control(peripheral_uart_h uart,
  */
 int peripheral_uart_read(peripheral_uart_h uart, uint8_t *data, uint32_t length);
 
+
+/**
+ * @platform
+ * @brief Discards data queued for writing to UART slave device, but not yet transmitted.
+ * @since_tizen 7.5
+ * @privlevel platform
+ * @privilege http://tizen.org/privilege/peripheralio
+ *
+ * @param[in] uart The UART handle
+ *
+ * @return #PERIPHERAL_ERROR_NONE on success, otherwise a negative error value
+ * @retval #PERIPHERAL_ERROR_NONE Successful
+ * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed
+ * @retval #PERIPHERAL_ERROR_TRY_AGAIN Try again
+ * @retval #PERIPHERAL_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PERIPHERAL_ERROR_NOT_SUPPORTED Not supported
+ * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error
+ *
+ */
+int peripheral_uart_flush(peripheral_uart_h uart);
+
+/**
+ * @platform
+ * @brief Waits for all data queued for UART to be transmitted.
+ * @since_tizen 7.5
+ * @privlevel platform
+ * @privilege http://tizen.org/privilege/peripheralio
+ *
+ * @param[in] uart The UART handle
+ *
+ * @return #PERIPHERAL_ERROR_NONE on success, otherwise a negative error value
+ * @retval #PERIPHERAL_ERROR_NONE Successful
+ * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed
+ * @retval #PERIPHERAL_ERROR_TRY_AGAIN Try again
+ * @retval #PERIPHERAL_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #PERIPHERAL_ERROR_NOT_SUPPORTED Not supported
+ * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error
+ *
+ */
+int peripheral_uart_drain(peripheral_uart_h uart);
+
 /**
  * @platform
  * @brief Writes data to the UART slave device.
index beb2434c2f9ef45e964da883b23b746bfa17ae31..3ee431dc4b0475a5b76806df803de8ef1023c1a9 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-system-peripheral-io
 Summary:    Tizen Peripheral Input & Output library
-Version:    0.3.2
+Version:    0.3.3
 Release:    0
 Group:      System & System Tools
 License:    Apache-2.0
index 544bb67c4979bb81a72596c22cfefab386a81ef2..45a1a54c8d949c4978c5cbfbebd53a0e41e4b468 100644 (file)
@@ -113,3 +113,8 @@ static inline int peripheral_get_lock_type(peripheral_open_flags_e flags)
                return LOCK_SH;
        return LOCK_EX;
 }
+
+static inline int peripheral_get_nonblock_flag(peripheral_open_flags_e flags)
+{
+       return flags & PERIPHERAL_OPEN_FLAGS_NONBLOCK ? O_NONBLOCK : 0;
+}
index 2e86a28d3c53917c934cfc0fd15a0f1f1cce7aa8..3cd2e134c842f62732ec7788f04d49d866de5122 100644 (file)
@@ -104,8 +104,15 @@ int peripheral_uart_open_flags(int port, peripheral_open_flags_e flags, peripher
        RETVM_IF(!__is_feature_supported(), PERIPHERAL_ERROR_NOT_SUPPORTED, "UART feature is not supported");
        RETVM_IF(uart == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid uart handle");
        RETVM_IF(port < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid port number");
-       RETVM_IF(flags != PERIPHERAL_OPEN_FLAGS_PRIVATE && flags != PERIPHERAL_OPEN_FLAGS_SHARED,
-                       PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid flags");
+
+       /* The PRIVATE flag is actually 0 and doesn't represent any bit,
+        * it's just there so people don't have to write a magic 0 constant
+        * for shared access. This means some care needs to be taken when
+        * manipulating it as a bitflag (in particular it is skipped here). */
+       static const int ALL_OPEN_FLAGS
+               = PERIPHERAL_OPEN_FLAGS_NONBLOCK
+               | PERIPHERAL_OPEN_FLAGS_SHARED;
+       RETVM_IF(flags & ~ALL_OPEN_FLAGS, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid flags");
 
        __attribute__ ((cleanup(cleanup_handlep))) peripheral_uart_h handle = (peripheral_uart_h)calloc(1, sizeof *handle);
        if (handle == NULL) {
@@ -120,7 +127,7 @@ int peripheral_uart_open_flags(int port, peripheral_open_flags_e flags, peripher
        };
 
        char path[DEV_PATH_FMT_MAX_SIZE] = {0, }; /* space for /dev/ttyXXX%d */
-       const int FLAGS = O_RDWR | O_NOCTTY | O_CLOEXEC;
+       const int FLAGS = O_RDWR | O_NOCTTY | O_CLOEXEC | peripheral_get_nonblock_flag(flags);
 
        int fd = -1;
        int retval = peripheral_uart_find_devpath(port, path, DEV_PATH_FMT_MAX_SIZE);
@@ -171,9 +178,26 @@ int peripheral_uart_open(int port, peripheral_uart_h *uart)
        return peripheral_uart_open_flags(port, PERIPHERAL_OPEN_FLAGS_PRIVATE, uart);
 }
 
-static void peripheral_uart_flush(peripheral_uart_h uart)
+int peripheral_uart_flush(peripheral_uart_h uart)
 {
-       tcflush(uart->fd, TCIOFLUSH);
+       RETVM_IF(!__is_feature_supported(), PERIPHERAL_ERROR_NOT_SUPPORTED, "UART feature is not supported");
+       RETVM_IF(uart == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "uart handle is NULL");
+
+       int ret = tcflush(uart->fd, TCIOFLUSH);
+       CHECK_ERROR(ret < 0);
+
+       return PERIPHERAL_ERROR_NONE;
+}
+
+int peripheral_uart_drain(peripheral_uart_h uart)
+{
+       RETVM_IF(!__is_feature_supported(), PERIPHERAL_ERROR_NOT_SUPPORTED, "UART feature is not supported");
+       RETVM_IF(uart == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "uart handle is NULL");
+
+       int ret = tcdrain(uart->fd);
+       CHECK_ERROR(ret < 0);
+
+       return PERIPHERAL_ERROR_NONE;
 }
 
 /**
@@ -213,7 +237,7 @@ int peripheral_uart_set_baud_rate(peripheral_uart_h uart, peripheral_uart_baud_r
        tio.c_cc[VMIN] = 1;
        tio.c_cc[VTIME] = 0;
 
-       peripheral_uart_flush(uart);
+       (void)peripheral_uart_flush(uart);
 
        ret = tcsetattr(uart->fd, TCSANOW, &tio);
        CHECK_ERROR(ret != 0);
@@ -238,7 +262,7 @@ int peripheral_uart_set_byte_size(peripheral_uart_h uart, peripheral_uart_byte_s
        tio.c_cflag |= byteinfo[byte_size];
        tio.c_cflag |= (CLOCAL | CREAD);
 
-       peripheral_uart_flush(uart);
+       (void)peripheral_uart_flush(uart);
 
        ret = tcsetattr(uart->fd, TCSANOW, &tio);
        CHECK_ERROR(ret != 0);
@@ -275,7 +299,7 @@ int peripheral_uart_set_parity(peripheral_uart_h uart, peripheral_uart_parity_e
                break;
        }
 
-       peripheral_uart_flush(uart);
+       (void)peripheral_uart_flush(uart);
 
        ret = tcsetattr(uart->fd, TCSANOW, &tio);
        CHECK_ERROR(ret != 0);
@@ -300,7 +324,7 @@ int peripheral_uart_set_stop_bits(peripheral_uart_h uart, peripheral_uart_stop_b
        else // PERIPHERAL_UART_STOP_BITS_2BIT
                tio.c_cflag |= CSTOPB;
 
-       peripheral_uart_flush(uart);
+       (void)peripheral_uart_flush(uart);
 
        ret = tcsetattr(uart->fd, TCSANOW, &tio);
        CHECK_ERROR(ret != 0);
@@ -334,7 +358,7 @@ int peripheral_uart_set_flow_control(peripheral_uart_h uart, peripheral_uart_sof
        else // PERIPHERAL_UART_SOFTWARE_FLOW_CONTROL_NONE
                tio.c_iflag &= ~(IXON | IXOFF | IXANY);
 
-       peripheral_uart_flush(uart);
+       (void)peripheral_uart_flush(uart);
 
        ret = tcsetattr(uart->fd, TCSANOW, &tio);
        CHECK_ERROR(ret != 0);