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