1 /*
2  * Copyright (c) 2022 Trackunit Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/types.h>
8 #include <zephyr/kernel.h>
9 
10 #ifndef ZEPHYR_MODEM_PIPE_
11 #define ZEPHYR_MODEM_PIPE_
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /**
18  * @brief Modem Pipe
19  * @defgroup modem_pipe Modem Pipe
20  * @ingroup modem
21  * @{
22  */
23 
24 /** Modem pipe event */
25 enum modem_pipe_event {
26 	MODEM_PIPE_EVENT_OPENED = 0,
27 	MODEM_PIPE_EVENT_RECEIVE_READY,
28 	MODEM_PIPE_EVENT_TRANSMIT_IDLE,
29 	MODEM_PIPE_EVENT_CLOSED,
30 };
31 
32 /**
33  * @cond INTERNAL_HIDDEN
34  */
35 
36 struct modem_pipe;
37 
38 /**
39  * @endcond
40  */
41 
42 typedef void (*modem_pipe_api_callback)(struct modem_pipe *pipe, enum modem_pipe_event event,
43 					void *user_data);
44 
45 /**
46  * @cond INTERNAL_HIDDEN
47  */
48 
49 typedef int (*modem_pipe_api_open)(void *data);
50 
51 typedef int (*modem_pipe_api_transmit)(void *data, const uint8_t *buf, size_t size);
52 
53 typedef int (*modem_pipe_api_receive)(void *data, uint8_t *buf, size_t size);
54 
55 typedef int (*modem_pipe_api_close)(void *data);
56 
57 struct modem_pipe_api {
58 	modem_pipe_api_open open;
59 	modem_pipe_api_transmit transmit;
60 	modem_pipe_api_receive receive;
61 	modem_pipe_api_close close;
62 };
63 
64 enum modem_pipe_state {
65 	MODEM_PIPE_STATE_CLOSED = 0,
66 	MODEM_PIPE_STATE_OPEN,
67 };
68 
69 struct modem_pipe {
70 	void *data;
71 	struct modem_pipe_api *api;
72 	modem_pipe_api_callback callback;
73 	void *user_data;
74 	enum modem_pipe_state state;
75 	struct k_mutex lock;
76 	struct k_condvar condvar;
77 	uint8_t receive_ready_pending : 1;
78 	uint8_t transmit_idle_pending : 1;
79 };
80 
81 /**
82  * @brief Initialize a modem pipe
83  *
84  * @param pipe Pipe instance to initialize
85  * @param data Pipe data to bind to pipe instance
86  * @param api Pipe API implementation to bind to pipe instance
87  */
88 void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api *api);
89 
90 /**
91  * @endcond
92  */
93 
94 /**
95  * @brief Open pipe
96  *
97  * @param pipe Pipe instance
98  *
99  * @retval 0 if pipe was successfully opened or was already open
100  * @retval -errno code otherwise
101  */
102 int modem_pipe_open(struct modem_pipe *pipe);
103 
104 /**
105  * @brief Open pipe asynchronously
106  *
107  * @param pipe Pipe instance
108  *
109  * @note The MODEM_PIPE_EVENT_OPENED event is invoked immediately if pipe is
110  * already opened.
111  *
112  * @retval 0 if pipe open was called successfully or pipe was already open
113  * @retval -errno code otherwise
114  */
115 int modem_pipe_open_async(struct modem_pipe *pipe);
116 
117 /**
118  * @brief Attach pipe to callback
119  *
120  * @param pipe Pipe instance
121  * @param callback Callback called when pipe event occurs
122  * @param user_data Free to use user data passed with callback
123  *
124  * @note The MODEM_PIPE_EVENT_RECEIVE_READY event is invoked immediately if pipe has pending
125  * data ready to receive.
126  */
127 void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback, void *user_data);
128 
129 /**
130  * @brief Transmit data through pipe
131  *
132  * @param pipe Pipe to transmit through
133  * @param buf Destination for reveived data
134  * @param size Capacity of destination for recevied data
135  *
136  * @return Number of bytes placed in pipe
137  *
138  * @warning This call must be non-blocking
139  */
140 int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size);
141 
142 /**
143  * @brief Reveive data through pipe
144  *
145  * @param pipe Pipe to receive from
146  * @param buf Destination for reveived data
147  * @param size Capacity of destination for recevied data
148  *
149  * @return Number of bytes received from pipe if any
150  * @return -EPERM if pipe is closed
151  * @return -errno code on error
152  *
153  * @warning This call must be non-blocking
154  */
155 int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size);
156 
157 /**
158  * @brief Clear callback
159  *
160  * @param pipe Pipe instance
161  */
162 void modem_pipe_release(struct modem_pipe *pipe);
163 
164 /**
165  * @brief Close pipe
166  *
167  * @param pipe Pipe instance
168  *
169  * @retval 0 if pipe open was called closed or pipe was already closed
170  * @retval -errno code otherwise
171  */
172 int modem_pipe_close(struct modem_pipe *pipe);
173 
174 /**
175  * @brief Close pipe asynchronously
176  *
177  * @param pipe Pipe instance
178  *
179  * @note The MODEM_PIPE_EVENT_CLOSED event is invoked immediately if pipe is
180  * already closed.
181  *
182  * @retval 0 if pipe close was called successfully or pipe was already closed
183  * @retval -errno code otherwise
184  */
185 int modem_pipe_close_async(struct modem_pipe *pipe);
186 
187 /**
188  * @cond INTERNAL_HIDDEN
189  */
190 
191 /**
192  * @brief Notify user of pipe that it has opened
193  *
194  * @param pipe Pipe instance
195  *
196  * @note Invoked from instance which initialized the pipe instance
197  */
198 void modem_pipe_notify_opened(struct modem_pipe *pipe);
199 
200 /**
201  * @brief Notify user of pipe that it has closed
202  *
203  * @param pipe Pipe instance
204  *
205  * @note Invoked from instance which initialized the pipe instance
206  */
207 void modem_pipe_notify_closed(struct modem_pipe *pipe);
208 
209 /**
210  * @brief Notify user of pipe that data is ready to be received
211  *
212  * @param pipe Pipe instance
213  *
214  * @note Invoked from instance which initialized the pipe instance
215  */
216 void modem_pipe_notify_receive_ready(struct modem_pipe *pipe);
217 
218 /**
219  * @brief Notify user of pipe that pipe has no more data to transmit
220  *
221  * @param pipe Pipe instance
222  *
223  * @note Invoked from instance which initialized the pipe instance
224  */
225 void modem_pipe_notify_transmit_idle(struct modem_pipe *pipe);
226 
227 /**
228  * @endcond
229  */
230 
231 /**
232  * @}
233  */
234 
235 #ifdef __cplusplus
236 }
237 #endif
238 
239 #endif /* ZEPHYR_MODEM_PIPE_ */
240