blob: 1df0c49acd5da2a5023f0a294e08ae4ca011a7b0 [file] [log] [blame]
Harald Weltea40c8e52019-09-27 19:22:34 +02001#pragma once
2#include <stdint.h>
3#include <stdbool.h>
4#include <osmocom/core/linuxlist.h>
Harald Welte7b64fc02019-10-09 20:49:35 +02005#include <osmocom/core/timer.h>
Harald Weltea40c8e52019-09-27 19:22:34 +02006
7#include <osmocom/core/select.h>
8#include "utils_ringbuffer.h"
9
Harald Welte03d6ebb2019-09-28 23:19:31 +020010struct usart_async_descriptor;
11
Harald Weltea40c8e52019-09-27 19:22:34 +020012enum card_uart_event {
13 /* a single byte was received, it's present at the (uint8_t *) data location */
14 CUART_E_RX_SINGLE,
15 /* an entire block of data was received */
16 CUART_E_RX_COMPLETE,
17 CUART_E_RX_TIMEOUT,
18 /* an entire block of data was written, as instructed in prior card_uart_tx() call */
19 CUART_E_TX_COMPLETE,
20};
21
22extern const struct value_string card_uart_event_vals[];
23
24enum card_uart_ctl {
Harald Welted4328e22019-10-10 10:07:50 +020025 CUART_CTL_RX, /* enable/disable receiver */
Eric Wild2f5cdd12019-11-27 18:40:44 +010026 CUART_CTL_RX_TIMER_HINT, /* tell cuart approximate number of rx bytes */
Eric Wildfd0bace2019-11-27 18:33:09 +010027 CUART_CTL_NO_RXTX, /* enable/disable receiver */
Harald Welted4328e22019-10-10 10:07:50 +020028 CUART_CTL_POWER, /* enable/disable ICC power */
29 CUART_CTL_CLOCK, /* enable/disable ICC clock */
Eric Wild587d4fb2019-11-27 18:59:43 +010030 CUART_CTL_SET_CLOCK_FREQ, /* set ICC clock frequency (hz)*/
Harald Welted4328e22019-10-10 10:07:50 +020031 CUART_CTL_RST, /* enable/disable ICC reset */
32 CUART_CTL_WTIME, /* set the waiting time (in etu) */
Eric Wild587d4fb2019-11-27 18:59:43 +010033 CUART_CTL_SET_FD,
Eric Wild9970ca02019-11-27 19:01:42 +010034 CUART_CTL_GET_BAUDRATE,
35 CUART_CTL_GET_CLOCK_FREQ,
Harald Weltea40c8e52019-09-27 19:22:34 +020036};
37
38struct card_uart;
39
40struct card_uart_ops {
41 int (*open)(struct card_uart *cuart, const char *device_name);
42 int (*close)(struct card_uart *cuart);
Harald Welte02dd9112019-10-01 08:55:29 +020043 int (*async_tx)(struct card_uart *cuart, const uint8_t *data, size_t len);
Harald Weltea40c8e52019-09-27 19:22:34 +020044 int (*async_rx)(struct card_uart *cuart, uint8_t *data, size_t len);
45
Harald Welte9700d392019-10-09 20:17:28 +020046 int (*ctrl)(struct card_uart *cuart, enum card_uart_ctl ctl, int arg);
Harald Weltea40c8e52019-09-27 19:22:34 +020047};
48
49/* Card UART driver */
50struct card_uart_driver {
51 /* global list of card UART drivers */
52 struct llist_head list;
53 /* human-readable name of driver */
54 const char *name;
55 /* operations implementing the driver */
56 const struct card_uart_ops *ops;
57};
58
59struct card_uart {
60 /* member in global list of UARTs */
61 struct llist_head list;
62 /* driver serving this UART */
63 const struct card_uart_driver *driver;
64 /* event-handler function */
65 void (*handle_event)(struct card_uart *cuart, enum card_uart_event evt, void *data);
66 /* opaque pointer for user */
67 void *priv;
68
69 /* is the transmitter currently busy (true) or not (false)? */
70 bool tx_busy;
71 /* is the receiver currently enabled or not? */
72 bool rx_enabled;
Harald Welte6603d952019-10-09 20:50:13 +020073 /* should the receiver automatically be nabled after TX completion? */
74 bool rx_after_tx_compl;
Harald Weltea40c8e52019-09-27 19:22:34 +020075
76 /*! after how many bytes should we notify the user? If this is '1', we will
77 * issue CUART_E_RX_SINGLE; if it is > 1, we will issue CUART_E_RX_COMPLETE */
78 uint32_t rx_threshold;
79
Harald Welte7b64fc02019-10-09 20:49:35 +020080 uint32_t wtime_etu;
81 struct osmo_timer_list wtime_tmr;
Eric Wild2f5cdd12019-11-27 18:40:44 +010082 /* expected number of bytes, for timeout */
83 uint32_t current_wtime_byte;
Harald Welte7b64fc02019-10-09 20:49:35 +020084
Harald Weltea40c8e52019-09-27 19:22:34 +020085 /* driver-specific private data */
86 union {
87 struct {
88 /* ringbuffer on receive side */
89 uint8_t rx_buf[256];
90 struct ringbuffer rx_ringbuf;
91
92 /* pointer to (user-allocated) transmit buffer and length */
93 const uint8_t *tx_buf;
94 size_t tx_buf_len;
95 /* index: offset of next to be transmitted byte in tx_buf */
96 size_t tx_index;
Harald Welte18ec3222019-09-28 21:41:59 +020097 /* number of bytes we have received echoed back during transmit */
98 uint32_t rx_count_during_tx;
Harald Weltea40c8e52019-09-27 19:22:34 +020099
100 struct osmo_fd ofd;
101 unsigned int baudrate;
102 } tty;
Harald Welte03d6ebb2019-09-28 23:19:31 +0200103 struct {
104 struct usart_async_descriptor *usa_pd;
105 uint8_t slot_nr;
Eric Wildb39d8322019-11-27 16:50:28 +0100106 /* in us, required, no delay breaks _rx_ */
107 uint32_t extrawait_after_rx;
Eric Wild9970ca02019-11-27 19:01:42 +0100108 uint32_t current_baudrate;
Harald Welte03d6ebb2019-09-28 23:19:31 +0200109 } asf4;
Harald Weltea40c8e52019-09-27 19:22:34 +0200110 } u;
111};
112
113/*! Open the Card UART */
114int card_uart_open(struct card_uart *cuart, const char *driver_name, const char *device_name);
115
116/*! Close the Card UART */
117int card_uart_close(struct card_uart *cuart);
118
119/*! Schedule (asynchronous) transmit data via UART; optionally enable Rx after completion */
Harald Welte6603d952019-10-09 20:50:13 +0200120int 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 +0200121
122/*! Schedule (asynchronous) receive data via UART (after CUART_E_RX_COMPLETE) */
123int card_uart_rx(struct card_uart *cuart, uint8_t *data, size_t len);
124
Harald Welte9700d392019-10-09 20:17:28 +0200125int card_uart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int arg);
Harald Weltea40c8e52019-09-27 19:22:34 +0200126
127/*! Set the Rx notification threshold in number of bytes received */
128void card_uart_set_rx_threshold(struct card_uart *cuart, size_t rx_threshold);
129
Harald Welte7b64fc02019-10-09 20:49:35 +0200130/* (re)start the software WTIME timer */
131void card_uart_wtime_restart(struct card_uart *cuart);
132
Harald Weltea40c8e52019-09-27 19:22:34 +0200133void card_uart_notification(struct card_uart *cuart, enum card_uart_event evt, void *data);
134
135int card_uart_driver_register(struct card_uart_driver *drv);