blob: e5ec501972aeff083e2bfe4980657df1f8120297 [file] [log] [blame]
Harald Weltea40c8e52019-09-27 19:22:34 +02001#pragma once
Harald Weltea67be5f2020-09-03 10:04:36 +02002/* Card UART handling
3 *
4 * (C) 2019-2020 by Harald Welte <laforge@gnumonks.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19 */
20
Harald Weltea40c8e52019-09-27 19:22:34 +020021#include <stdint.h>
22#include <stdbool.h>
23#include <osmocom/core/linuxlist.h>
Harald Welte7b64fc02019-10-09 20:49:35 +020024#include <osmocom/core/timer.h>
Harald Weltea40c8e52019-09-27 19:22:34 +020025
26#include <osmocom/core/select.h>
27#include "utils_ringbuffer.h"
28
Harald Welte03d6ebb2019-09-28 23:19:31 +020029struct usart_async_descriptor;
30
Harald Weltea40c8e52019-09-27 19:22:34 +020031enum card_uart_event {
32 /* a single byte was received, it's present at the (uint8_t *) data location */
33 CUART_E_RX_SINGLE,
34 /* an entire block of data was received */
35 CUART_E_RX_COMPLETE,
36 CUART_E_RX_TIMEOUT,
37 /* an entire block of data was written, as instructed in prior card_uart_tx() call */
38 CUART_E_TX_COMPLETE,
39};
40
41extern const struct value_string card_uart_event_vals[];
42
43enum card_uart_ctl {
Harald Welted4328e22019-10-10 10:07:50 +020044 CUART_CTL_RX, /* enable/disable receiver */
Eric Wild2f5cdd12019-11-27 18:40:44 +010045 CUART_CTL_RX_TIMER_HINT, /* tell cuart approximate number of rx bytes */
Eric Wildfd0bace2019-11-27 18:33:09 +010046 CUART_CTL_NO_RXTX, /* enable/disable receiver */
Eric Wild70f36912020-04-03 22:29:02 +020047 CUART_CTL_POWER_5V0,
48 CUART_CTL_POWER_3V0,
49 CUART_CTL_POWER_1V8,
Harald Welted4328e22019-10-10 10:07:50 +020050 CUART_CTL_CLOCK, /* enable/disable ICC clock */
Eric Wild587d4fb2019-11-27 18:59:43 +010051 CUART_CTL_SET_CLOCK_FREQ, /* set ICC clock frequency (hz)*/
Harald Welted4328e22019-10-10 10:07:50 +020052 CUART_CTL_RST, /* enable/disable ICC reset */
53 CUART_CTL_WTIME, /* set the waiting time (in etu) */
Eric Wild587d4fb2019-11-27 18:59:43 +010054 CUART_CTL_SET_FD,
Eric Wild9970ca02019-11-27 19:01:42 +010055 CUART_CTL_GET_BAUDRATE,
56 CUART_CTL_GET_CLOCK_FREQ,
Harald Weltea40c8e52019-09-27 19:22:34 +020057};
58
59struct card_uart;
60
61struct card_uart_ops {
62 int (*open)(struct card_uart *cuart, const char *device_name);
63 int (*close)(struct card_uart *cuart);
Harald Welte02dd9112019-10-01 08:55:29 +020064 int (*async_tx)(struct card_uart *cuart, const uint8_t *data, size_t len);
Harald Weltea40c8e52019-09-27 19:22:34 +020065 int (*async_rx)(struct card_uart *cuart, uint8_t *data, size_t len);
66
Harald Welte9700d392019-10-09 20:17:28 +020067 int (*ctrl)(struct card_uart *cuart, enum card_uart_ctl ctl, int arg);
Harald Weltea40c8e52019-09-27 19:22:34 +020068};
69
70/* Card UART driver */
71struct card_uart_driver {
72 /* global list of card UART drivers */
73 struct llist_head list;
74 /* human-readable name of driver */
75 const char *name;
76 /* operations implementing the driver */
77 const struct card_uart_ops *ops;
78};
79
80struct card_uart {
81 /* member in global list of UARTs */
82 struct llist_head list;
83 /* driver serving this UART */
84 const struct card_uart_driver *driver;
85 /* event-handler function */
86 void (*handle_event)(struct card_uart *cuart, enum card_uart_event evt, void *data);
87 /* opaque pointer for user */
88 void *priv;
89
90 /* is the transmitter currently busy (true) or not (false)? */
91 bool tx_busy;
92 /* is the receiver currently enabled or not? */
93 bool rx_enabled;
Harald Welte6603d952019-10-09 20:50:13 +020094 /* should the receiver automatically be nabled after TX completion? */
95 bool rx_after_tx_compl;
Harald Weltea40c8e52019-09-27 19:22:34 +020096
97 /*! after how many bytes should we notify the user? If this is '1', we will
98 * issue CUART_E_RX_SINGLE; if it is > 1, we will issue CUART_E_RX_COMPLETE */
99 uint32_t rx_threshold;
100
Harald Welte7b64fc02019-10-09 20:49:35 +0200101 uint32_t wtime_etu;
102 struct osmo_timer_list wtime_tmr;
Eric Wild2f5cdd12019-11-27 18:40:44 +0100103 /* expected number of bytes, for timeout */
104 uint32_t current_wtime_byte;
Harald Welte7b64fc02019-10-09 20:49:35 +0200105
Harald Weltea40c8e52019-09-27 19:22:34 +0200106 /* driver-specific private data */
107 union {
108 struct {
109 /* ringbuffer on receive side */
110 uint8_t rx_buf[256];
111 struct ringbuffer rx_ringbuf;
112
113 /* pointer to (user-allocated) transmit buffer and length */
114 const uint8_t *tx_buf;
115 size_t tx_buf_len;
116 /* index: offset of next to be transmitted byte in tx_buf */
117 size_t tx_index;
Harald Welte18ec3222019-09-28 21:41:59 +0200118 /* number of bytes we have received echoed back during transmit */
119 uint32_t rx_count_during_tx;
Harald Weltea40c8e52019-09-27 19:22:34 +0200120
121 struct osmo_fd ofd;
122 unsigned int baudrate;
123 } tty;
Harald Welte03d6ebb2019-09-28 23:19:31 +0200124 struct {
125 struct usart_async_descriptor *usa_pd;
126 uint8_t slot_nr;
Eric Wildb39d8322019-11-27 16:50:28 +0100127 /* in us, required, no delay breaks _rx_ */
128 uint32_t extrawait_after_rx;
Eric Wild9970ca02019-11-27 19:01:42 +0100129 uint32_t current_baudrate;
Harald Welte03d6ebb2019-09-28 23:19:31 +0200130 } asf4;
Harald Weltea40c8e52019-09-27 19:22:34 +0200131 } u;
132};
133
134/*! Open the Card UART */
135int card_uart_open(struct card_uart *cuart, const char *driver_name, const char *device_name);
136
137/*! Close the Card UART */
138int card_uart_close(struct card_uart *cuart);
139
140/*! Schedule (asynchronous) transmit data via UART; optionally enable Rx after completion */
Harald Welte6603d952019-10-09 20:50:13 +0200141int card_uart_tx(struct card_uart *cuart, const uint8_t *data, size_t len, bool rx_after_complete);
Harald Weltea40c8e52019-09-27 19:22:34 +0200142
143/*! Schedule (asynchronous) receive data via UART (after CUART_E_RX_COMPLETE) */
144int card_uart_rx(struct card_uart *cuart, uint8_t *data, size_t len);
145
Harald Welte9700d392019-10-09 20:17:28 +0200146int card_uart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int arg);
Harald Weltea40c8e52019-09-27 19:22:34 +0200147
148/*! Set the Rx notification threshold in number of bytes received */
149void card_uart_set_rx_threshold(struct card_uart *cuart, size_t rx_threshold);
150
Harald Welte7b64fc02019-10-09 20:49:35 +0200151/* (re)start the software WTIME timer */
152void card_uart_wtime_restart(struct card_uart *cuart);
153
Harald Weltea40c8e52019-09-27 19:22:34 +0200154void card_uart_notification(struct card_uart *cuart, enum card_uart_event evt, void *data);
155
156int card_uart_driver_register(struct card_uart_driver *drv);