1 /*
2 * Copyright (c) 2022 Trackunit Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/modem/pipe.h>
8
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(modem_pipe, CONFIG_MODEM_MODULES_LOG_LEVEL);
11
modem_pipe_init(struct modem_pipe * pipe,void * data,struct modem_pipe_api * api)12 void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api *api)
13 {
14 __ASSERT_NO_MSG(pipe != NULL);
15 __ASSERT_NO_MSG(data != NULL);
16 __ASSERT_NO_MSG(api != NULL);
17
18 pipe->data = data;
19 pipe->api = api;
20 pipe->callback = NULL;
21 pipe->user_data = NULL;
22 pipe->state = MODEM_PIPE_STATE_CLOSED;
23 pipe->receive_ready_pending = false;
24
25 k_mutex_init(&pipe->lock);
26 k_condvar_init(&pipe->condvar);
27 }
28
modem_pipe_open(struct modem_pipe * pipe)29 int modem_pipe_open(struct modem_pipe *pipe)
30 {
31 int ret;
32
33 k_mutex_lock(&pipe->lock, K_FOREVER);
34 if (pipe->state == MODEM_PIPE_STATE_OPEN) {
35 k_mutex_unlock(&pipe->lock);
36 return 0;
37 }
38
39 ret = pipe->api->open(pipe->data);
40 if (ret < 0) {
41 k_mutex_unlock(&pipe->lock);
42 return ret;
43 }
44
45 if (pipe->state == MODEM_PIPE_STATE_OPEN) {
46 k_mutex_unlock(&pipe->lock);
47 return 0;
48 }
49
50 k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000));
51 ret = (pipe->state == MODEM_PIPE_STATE_OPEN) ? 0 : -EAGAIN;
52 k_mutex_unlock(&pipe->lock);
53 return ret;
54 }
55
modem_pipe_open_async(struct modem_pipe * pipe)56 int modem_pipe_open_async(struct modem_pipe *pipe)
57 {
58 int ret;
59
60 k_mutex_lock(&pipe->lock, K_FOREVER);
61 if (pipe->state == MODEM_PIPE_STATE_OPEN) {
62 if (pipe->callback != NULL) {
63 pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data);
64 }
65
66 k_mutex_unlock(&pipe->lock);
67 return 0;
68 }
69
70 ret = pipe->api->open(pipe->data);
71 k_mutex_unlock(&pipe->lock);
72 return ret;
73 }
74
modem_pipe_attach(struct modem_pipe * pipe,modem_pipe_api_callback callback,void * user_data)75 void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback, void *user_data)
76 {
77 k_mutex_lock(&pipe->lock, K_FOREVER);
78 pipe->callback = callback;
79 pipe->user_data = user_data;
80
81 if (pipe->receive_ready_pending && (pipe->callback != NULL)) {
82 pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data);
83 }
84
85 k_mutex_unlock(&pipe->lock);
86 }
87
modem_pipe_transmit(struct modem_pipe * pipe,const uint8_t * buf,size_t size)88 int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size)
89 {
90 int ret;
91
92 k_mutex_lock(&pipe->lock, K_FOREVER);
93
94 if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
95 k_mutex_unlock(&pipe->lock);
96 return -EPERM;
97 }
98
99 ret = pipe->api->transmit(pipe->data, buf, size);
100 k_mutex_unlock(&pipe->lock);
101 return ret;
102 }
103
modem_pipe_receive(struct modem_pipe * pipe,uint8_t * buf,size_t size)104 int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size)
105 {
106 int ret;
107
108 k_mutex_lock(&pipe->lock, K_FOREVER);
109
110 if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
111 k_mutex_unlock(&pipe->lock);
112 return -EPERM;
113 }
114
115 ret = pipe->api->receive(pipe->data, buf, size);
116 pipe->receive_ready_pending = false;
117 k_mutex_unlock(&pipe->lock);
118 return ret;
119 }
120
modem_pipe_release(struct modem_pipe * pipe)121 void modem_pipe_release(struct modem_pipe *pipe)
122 {
123 k_mutex_lock(&pipe->lock, K_FOREVER);
124 pipe->callback = NULL;
125 pipe->user_data = NULL;
126 k_mutex_unlock(&pipe->lock);
127 }
128
modem_pipe_close(struct modem_pipe * pipe)129 int modem_pipe_close(struct modem_pipe *pipe)
130 {
131 int ret;
132
133 k_mutex_lock(&pipe->lock, K_FOREVER);
134 if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
135 k_mutex_unlock(&pipe->lock);
136 return 0;
137 }
138
139 ret = pipe->api->close(pipe->data);
140 if (ret < 0) {
141 k_mutex_unlock(&pipe->lock);
142 return ret;
143 }
144
145 if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
146 k_mutex_unlock(&pipe->lock);
147 return 0;
148 }
149
150 k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000));
151 ret = (pipe->state == MODEM_PIPE_STATE_CLOSED) ? 0 : -EAGAIN;
152 k_mutex_unlock(&pipe->lock);
153 return ret;
154 }
155
modem_pipe_close_async(struct modem_pipe * pipe)156 int modem_pipe_close_async(struct modem_pipe *pipe)
157 {
158 int ret;
159
160 k_mutex_lock(&pipe->lock, K_FOREVER);
161 if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
162 if (pipe->callback != NULL) {
163 pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data);
164 }
165
166 k_mutex_unlock(&pipe->lock);
167 return 0;
168 }
169
170 ret = pipe->api->close(pipe->data);
171 k_mutex_unlock(&pipe->lock);
172 return ret;
173 }
174
modem_pipe_notify_opened(struct modem_pipe * pipe)175 void modem_pipe_notify_opened(struct modem_pipe *pipe)
176 {
177 k_mutex_lock(&pipe->lock, K_FOREVER);
178 pipe->state = MODEM_PIPE_STATE_OPEN;
179
180 if (pipe->callback != NULL) {
181 pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data);
182 }
183
184 k_condvar_signal(&pipe->condvar);
185 k_mutex_unlock(&pipe->lock);
186 }
187
modem_pipe_notify_closed(struct modem_pipe * pipe)188 void modem_pipe_notify_closed(struct modem_pipe *pipe)
189 {
190 k_mutex_lock(&pipe->lock, K_FOREVER);
191 pipe->state = MODEM_PIPE_STATE_CLOSED;
192 pipe->receive_ready_pending = false;
193
194 if (pipe->callback != NULL) {
195 pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data);
196 }
197
198 k_condvar_signal(&pipe->condvar);
199 k_mutex_unlock(&pipe->lock);
200 }
201
modem_pipe_notify_receive_ready(struct modem_pipe * pipe)202 void modem_pipe_notify_receive_ready(struct modem_pipe *pipe)
203 {
204 k_mutex_lock(&pipe->lock, K_FOREVER);
205
206 pipe->receive_ready_pending = true;
207
208 if (pipe->callback != NULL) {
209 pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data);
210 }
211
212 k_mutex_unlock(&pipe->lock);
213 }
214