blob: afc6ad6db0382fb08ab7f04af916a72dc04fee7b [file] [log] [blame]
Harald Weltedc023cf2022-11-29 23:15:18 +01001#pragma once
2
3/*! \file soft_uart.h
4 * Software UART implementation. */
5/*
6 * (C) 2022 by Harald Welte <laforge@gnumonks.org>
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +07007 * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
Harald Weltedc023cf2022-11-29 23:15:18 +01008 *
9 * All Rights Reserved
10 *
11 * SPDX-License-Identifier: GPL-2.0+
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 */
24
25#include <stdint.h>
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +070026#include <stdbool.h>
27
Harald Weltedc023cf2022-11-29 23:15:18 +010028#include <osmocom/core/bits.h>
29#include <osmocom/core/msgb.h>
30
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070031/*! Parity mode.
32 * https://en.wikipedia.org/wiki/Parity_bit */
Harald Weltedc023cf2022-11-29 23:15:18 +010033enum osmo_soft_uart_parity_mode {
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070034 OSMO_SUART_PARITY_NONE, /*!< No parity bit */
35 OSMO_SUART_PARITY_EVEN, /*!< Even parity */
36 OSMO_SUART_PARITY_ODD, /*!< Odd parity */
37 OSMO_SUART_PARITY_MARK, /*!< Always 1 */
38 OSMO_SUART_PARITY_SPACE, /*!< Always 0 */
Harald Weltedc023cf2022-11-29 23:15:18 +010039 _OSMO_SUART_PARITY_NUM
40};
41
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070042/*! Flags passed to the application. */
Harald Weltedc023cf2022-11-29 23:15:18 +010043enum osmo_soft_uart_flags {
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070044 OSMO_SUART_F_FRAMING_ERROR = (1 << 0), /*!< Framing error occurred */
45 OSMO_SUART_F_PARITY_ERROR = (1 << 1), /*!< Parity error occurred */
46 OSMO_SUART_F_BREAK = (1 << 2), /*!< Break condition (not implemented) */
Harald Weltedc023cf2022-11-29 23:15:18 +010047};
48
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +070049/*! Modem status "line" flags.
50 * https://en.wikipedia.org/wiki/RS-232#Data_and_control_signals */
Harald Weltedc023cf2022-11-29 23:15:18 +010051enum osmo_soft_uart_status {
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +070052 OSMO_SUART_STATUS_F_DTR = (1 << 0), /*!< Data Terminal Ready */
53 OSMO_SUART_STATUS_F_DCD = (1 << 1), /*!< Data Carrier Detect */
54 OSMO_SUART_STATUS_F_DSR = (1 << 2), /*!< Data Set Ready */
55 OSMO_SUART_STATUS_F_RI = (1 << 3), /*!< Ring Indicator */
56 OSMO_SUART_STATUS_F_RTS_RTR = (1 << 4), /*!< Request To Send or Ready To Receive */
57 OSMO_SUART_STATUS_F_CTS = (1 << 5), /*!< Clear To Send */
Harald Weltedc023cf2022-11-29 23:15:18 +010058};
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +070059
60/*! Flow control mode.
61 * https://en.wikipedia.org/wiki/Flow_control_(data)#Hardware_flow_control */
62enum osmo_soft_uart_flow_ctrl_mode {
63 /*! No flow control */
64 OSMO_SUART_FLOW_CTRL_NONE,
65 /*! DTR/DSR flow control: Tx if DSR is active and drop DTR if cannot Rx anymore. */
66 OSMO_SUART_FLOW_CTRL_DTR_DSR,
67 /*! RTS/CTS flow control: Tx if CTS is active and drop RTS if cannot Rx anymore.
68 * The technically correct name would be RTR/CTS, because the RTS signal actually
69 * indicates readiness to *receive* data (Ready To Receive), and not really used
70 * to request a transmission (Request To Send) nowadays. Alternatively, the RTS
71 * signal can be interpreted as "Request To Send to me". */
72 OSMO_SUART_FLOW_CTRL_RTS_CTS,
73};
Harald Weltedc023cf2022-11-29 23:15:18 +010074
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070075/*! Configuration for a soft-UART. */
Harald Weltedc023cf2022-11-29 23:15:18 +010076struct osmo_soft_uart_cfg {
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070077 /*! Number of data bits (typically 5, 6, 7 or 8). */
Harald Weltedc023cf2022-11-29 23:15:18 +010078 uint8_t num_data_bits;
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070079 /*! Number of stop bits (typically 1 or 2). */
Harald Weltedc023cf2022-11-29 23:15:18 +010080 uint8_t num_stop_bits;
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070081 /*! Parity mode (none, even, odd, space, mark). */
Harald Weltedc023cf2022-11-29 23:15:18 +010082 enum osmo_soft_uart_parity_mode parity_mode;
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070083 /*! Size of the receive buffer; UART will buffer up to that number
84 * of characters before calling the receive call-back. */
Harald Weltedc023cf2022-11-29 23:15:18 +010085 unsigned int rx_buf_size;
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070086 /*! Receive timeout; UART will flush the receive buffer via the receive call-back
87 * after indicated number of milliseconds, even if it is not full yet. */
Harald Weltedc023cf2022-11-29 23:15:18 +010088 unsigned int rx_timeout_ms;
89
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070090 /*! Opaque application-private data; passed to call-backs. */
Harald Weltedc023cf2022-11-29 23:15:18 +010091 void *priv;
92
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +070093 /*! Receive call-back of the application.
94 *
95 * Called if at least one of the following conditions is met:
96 * a) rx_buf_size characters were received (Rx buffer is full);
97 * b) rx_timeout_ms expired and Rx buffer is not empty;
98 * c) a parity or framing error is occurred.
99 *
100 * \param[in] priv opaque application-private data.
101 * \param[in] rx_data msgb holding the received data.
102 * Must be free()ed by the application.
103 * \param[in] flags bit-mask of OSMO_SUART_F_*. */
Harald Weltedc023cf2022-11-29 23:15:18 +0100104 void (*rx_cb)(void *priv, struct msgb *rx_data, unsigned int flags);
105
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +0700106 /*! Transmit call-back of the application.
107 *
108 * The implementation is expected to provide at most tx_data->data_len
109 * characters (the actual amount is determined by the number of requested
110 * bits and the effective UART configuration).
111 *
112 * \param[in] priv opaque application-private data.
113 * \param[inout] tx_data msgb for writing to be transmitted data. */
Vadim Yanitskiyc9fc77f2023-11-16 00:55:35 +0700114 void (*tx_cb)(void *priv, struct msgb *tx_data);
115
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +0700116 /*! Modem status line change call-back.
Vadim Yanitskiy275c86e2023-12-04 01:44:09 +0700117 * \param[in] priv opaque application-private data.
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +0700118 * \param[in] status updated status; bit-mask of OSMO_SUART_STATUS_F_*. */
Harald Weltedc023cf2022-11-29 23:15:18 +0100119 void (*status_change_cb)(void *priv, unsigned int status);
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +0700120
121 /*! "Hardware" flow control mode. */
122 enum osmo_soft_uart_flow_ctrl_mode flow_ctrl_mode;
Harald Weltedc023cf2022-11-29 23:15:18 +0100123};
124
Vadim Yanitskiy82a1ae72023-11-16 15:34:50 +0700125extern const struct osmo_soft_uart_cfg osmo_soft_uart_default_cfg;
126
Harald Weltedc023cf2022-11-29 23:15:18 +0100127struct osmo_soft_uart;
128
Vadim Yanitskiy82a1ae72023-11-16 15:34:50 +0700129struct osmo_soft_uart *osmo_soft_uart_alloc(void *ctx, const char *name,
130 const struct osmo_soft_uart_cfg *cfg);
Vadim Yanitskiy877cfed2023-11-12 17:21:31 +0700131void osmo_soft_uart_free(struct osmo_soft_uart *suart);
Harald Weltedc023cf2022-11-29 23:15:18 +0100132int osmo_soft_uart_configure(struct osmo_soft_uart *suart, const struct osmo_soft_uart_cfg *cfg);
Vadim Yanitskiy59afb8f2023-11-29 23:58:10 +0700133
134const char *osmo_soft_uart_get_name(const struct osmo_soft_uart *suart);
135void osmo_soft_uart_set_name(struct osmo_soft_uart *suart, const char *name);
136
Vadim Yanitskiycdde6712023-11-16 15:17:37 +0700137int osmo_soft_uart_set_rx(struct osmo_soft_uart *suart, bool enable);
138int osmo_soft_uart_set_tx(struct osmo_soft_uart *suart, bool enable);
Harald Weltedc023cf2022-11-29 23:15:18 +0100139
140int osmo_soft_uart_rx_ubits(struct osmo_soft_uart *suart, const ubit_t *ubits, size_t n_ubits);
141int osmo_soft_uart_tx_ubits(struct osmo_soft_uart *suart, ubit_t *ubits, size_t n_ubits);
142
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +0700143unsigned int osmo_soft_uart_get_status(const struct osmo_soft_uart *suart);
Harald Weltedc023cf2022-11-29 23:15:18 +0100144int osmo_soft_uart_set_status(struct osmo_soft_uart *suart, unsigned int status);
Vadim Yanitskiy6587dd02023-11-30 03:04:32 +0700145void osmo_soft_uart_set_status_line(struct osmo_soft_uart *suart,
146 enum osmo_soft_uart_status line,
147 bool active);
148
Vadim Yanitskiy03f0ed72023-11-18 00:29:08 +0700149void osmo_soft_uart_flush_rx(struct osmo_soft_uart *suart);