1 /*
2 * Copyright (c) 2022 Trackunit Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/net/ppp.h>
8 #include <zephyr/sys/crc.h>
9 #include <zephyr/modem/ppp.h>
10 #include <string.h>
11
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(modem_ppp, CONFIG_MODEM_MODULES_LOG_LEVEL);
14
15 #define MODEM_PPP_STATE_ATTACHED_BIT (0)
16 #define MODEM_PPP_FRAME_TAIL_SIZE (2)
17
18 #define MODEM_PPP_CODE_DELIMITER (0x7E)
19 #define MODEM_PPP_CODE_ESCAPE (0x7D)
20 #define MODEM_PPP_VALUE_ESCAPE (0x20)
21
modem_ppp_fcs_init(uint8_t byte)22 static uint16_t modem_ppp_fcs_init(uint8_t byte)
23 {
24 return crc16_ccitt(0xFFFF, &byte, 1);
25 }
26
modem_ppp_fcs_update(uint16_t fcs,uint8_t byte)27 static uint16_t modem_ppp_fcs_update(uint16_t fcs, uint8_t byte)
28 {
29 return crc16_ccitt(fcs, &byte, 1);
30 }
31
modem_ppp_fcs_final(uint16_t fcs)32 static uint16_t modem_ppp_fcs_final(uint16_t fcs)
33 {
34 return fcs ^ 0xFFFF;
35 }
36
modem_ppp_ppp_protocol(struct net_pkt * pkt)37 static uint16_t modem_ppp_ppp_protocol(struct net_pkt *pkt)
38 {
39 if (net_pkt_family(pkt) == AF_INET) {
40 return PPP_IP;
41 }
42
43 if (net_pkt_family(pkt) == AF_INET6) {
44 return PPP_IPV6;
45 }
46
47 LOG_WRN("Unsupported protocol");
48 return 0;
49 }
50
modem_ppp_wrap_net_pkt_byte(struct modem_ppp * ppp)51 static uint8_t modem_ppp_wrap_net_pkt_byte(struct modem_ppp *ppp)
52 {
53 uint8_t byte;
54
55 switch (ppp->transmit_state) {
56 case MODEM_PPP_TRANSMIT_STATE_IDLE:
57 LOG_WRN("Invalid transmit state");
58 return 0;
59
60 /* Writing header */
61 case MODEM_PPP_TRANSMIT_STATE_SOF:
62 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_HDR_FF;
63 return MODEM_PPP_CODE_DELIMITER;
64
65 case MODEM_PPP_TRANSMIT_STATE_HDR_FF:
66 net_pkt_cursor_init(ppp->tx_pkt);
67 ppp->tx_pkt_fcs = modem_ppp_fcs_init(0xFF);
68 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_HDR_7D;
69 return 0xFF;
70
71 case MODEM_PPP_TRANSMIT_STATE_HDR_7D:
72 ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, 0x03);
73 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_HDR_23;
74 return MODEM_PPP_CODE_ESCAPE;
75
76 case MODEM_PPP_TRANSMIT_STATE_HDR_23:
77 if (net_pkt_is_ppp(ppp->tx_pkt) == true) {
78 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA;
79 } else {
80 ppp->tx_pkt_protocol = modem_ppp_ppp_protocol(ppp->tx_pkt);
81 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_PROTOCOL_HIGH;
82 }
83
84 return 0x23;
85
86 /* Writing protocol */
87 case MODEM_PPP_TRANSMIT_STATE_PROTOCOL_HIGH:
88 byte = (ppp->tx_pkt_protocol >> 8) & 0xFF;
89 ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, byte);
90
91 if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) ||
92 (byte < MODEM_PPP_VALUE_ESCAPE)) {
93 ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE;
94 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_HIGH;
95 return MODEM_PPP_CODE_ESCAPE;
96 }
97
98 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW;
99 return byte;
100
101 case MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_HIGH:
102 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW;
103 return ppp->tx_pkt_escaped;
104
105 case MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW:
106 byte = ppp->tx_pkt_protocol & 0xFF;
107 ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, byte);
108
109 if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) ||
110 (byte < MODEM_PPP_VALUE_ESCAPE)) {
111 ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE;
112 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_LOW;
113 return MODEM_PPP_CODE_ESCAPE;
114 }
115
116 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA;
117 return byte;
118
119 case MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_LOW:
120 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA;
121 return ppp->tx_pkt_escaped;
122
123 /* Writing data */
124 case MODEM_PPP_TRANSMIT_STATE_DATA:
125 (void)net_pkt_read_u8(ppp->tx_pkt, &byte);
126 ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, byte);
127
128 if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) ||
129 (byte < MODEM_PPP_VALUE_ESCAPE)) {
130 ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE;
131 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_DATA;
132 return MODEM_PPP_CODE_ESCAPE;
133 }
134
135 if (net_pkt_remaining_data(ppp->tx_pkt) == 0) {
136 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_LOW;
137 }
138
139 return byte;
140
141 case MODEM_PPP_TRANSMIT_STATE_ESCAPING_DATA:
142 if (net_pkt_remaining_data(ppp->tx_pkt) == 0) {
143 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_LOW;
144 } else {
145 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA;
146 }
147
148 return ppp->tx_pkt_escaped;
149
150 /* Writing FCS */
151 case MODEM_PPP_TRANSMIT_STATE_FCS_LOW:
152 ppp->tx_pkt_fcs = modem_ppp_fcs_final(ppp->tx_pkt_fcs);
153 byte = ppp->tx_pkt_fcs & 0xFF;
154
155 if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) ||
156 (byte < MODEM_PPP_VALUE_ESCAPE)) {
157 ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE;
158 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_LOW;
159 return MODEM_PPP_CODE_ESCAPE;
160 }
161
162 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_HIGH;
163 return byte;
164
165 case MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_LOW:
166 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_HIGH;
167 return ppp->tx_pkt_escaped;
168
169 case MODEM_PPP_TRANSMIT_STATE_FCS_HIGH:
170 byte = (ppp->tx_pkt_fcs >> 8) & 0xFF;
171
172 if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) ||
173 (byte < MODEM_PPP_VALUE_ESCAPE)) {
174 ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE;
175 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_HIGH;
176 return MODEM_PPP_CODE_ESCAPE;
177 }
178
179 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_EOF;
180 return byte;
181
182 case MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_HIGH:
183 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_EOF;
184 return ppp->tx_pkt_escaped;
185
186 /* Writing end of frame */
187 case MODEM_PPP_TRANSMIT_STATE_EOF:
188 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_IDLE;
189 return MODEM_PPP_CODE_DELIMITER;
190 }
191
192 return 0;
193 }
194
modem_ppp_is_byte_expected(uint8_t byte,uint8_t expected_byte)195 static bool modem_ppp_is_byte_expected(uint8_t byte, uint8_t expected_byte)
196 {
197 if (byte == expected_byte) {
198 return true;
199 }
200 LOG_DBG("Dropping byte 0x%02hhx because 0x%02hhx was expected.", byte, expected_byte);
201 return false;
202 }
203
modem_ppp_process_received_byte(struct modem_ppp * ppp,uint8_t byte)204 static void modem_ppp_process_received_byte(struct modem_ppp *ppp, uint8_t byte)
205 {
206 switch (ppp->receive_state) {
207 case MODEM_PPP_RECEIVE_STATE_HDR_SOF:
208 if (modem_ppp_is_byte_expected(byte, MODEM_PPP_CODE_DELIMITER)) {
209 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_FF;
210 }
211 break;
212
213 case MODEM_PPP_RECEIVE_STATE_HDR_FF:
214 if (byte == MODEM_PPP_CODE_DELIMITER) {
215 break;
216 }
217 if (modem_ppp_is_byte_expected(byte, 0xFF)) {
218 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_7D;
219 } else {
220 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
221 }
222 break;
223
224 case MODEM_PPP_RECEIVE_STATE_HDR_7D:
225 if (modem_ppp_is_byte_expected(byte, MODEM_PPP_CODE_ESCAPE)) {
226 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_23;
227 } else {
228 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
229 }
230 break;
231
232 case MODEM_PPP_RECEIVE_STATE_HDR_23:
233 if (modem_ppp_is_byte_expected(byte, 0x23)) {
234 ppp->rx_pkt = net_pkt_rx_alloc_with_buffer(ppp->iface,
235 CONFIG_MODEM_PPP_NET_BUF_FRAG_SIZE, AF_UNSPEC, 0, K_NO_WAIT);
236
237 if (ppp->rx_pkt == NULL) {
238 LOG_WRN("Dropped frame, no net_pkt available");
239 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
240 break;
241 }
242
243 LOG_DBG("Receiving PPP frame");
244 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_WRITING;
245 net_pkt_cursor_init(ppp->rx_pkt);
246 } else {
247 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
248 }
249
250 break;
251
252 case MODEM_PPP_RECEIVE_STATE_WRITING:
253 if (byte == MODEM_PPP_CODE_DELIMITER) {
254 LOG_DBG("Received PPP frame (len %zu)", net_pkt_get_len(ppp->rx_pkt));
255
256 /* Remove FCS */
257 net_pkt_remove_tail(ppp->rx_pkt, MODEM_PPP_FRAME_TAIL_SIZE);
258 net_pkt_set_ppp(ppp->rx_pkt, true);
259
260 if (net_recv_data(ppp->iface, ppp->rx_pkt) < 0) {
261 LOG_WRN("Net pkt could not be processed");
262 net_pkt_unref(ppp->rx_pkt);
263 }
264
265 ppp->rx_pkt = NULL;
266 /* Skip SOF because the delimiter may be omitted for successive frames. */
267 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_FF;
268 break;
269 }
270
271 if (net_pkt_available_buffer(ppp->rx_pkt) == 1) {
272 if (net_pkt_alloc_buffer(ppp->rx_pkt, CONFIG_MODEM_PPP_NET_BUF_FRAG_SIZE,
273 AF_INET, K_NO_WAIT) < 0) {
274 LOG_WRN("Failed to alloc buffer");
275 net_pkt_unref(ppp->rx_pkt);
276 ppp->rx_pkt = NULL;
277 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
278 break;
279 }
280 }
281
282 if (byte == MODEM_PPP_CODE_ESCAPE) {
283 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_UNESCAPING;
284 break;
285 }
286
287 if (net_pkt_write_u8(ppp->rx_pkt, byte) < 0) {
288 LOG_WRN("Dropped PPP frame");
289 net_pkt_unref(ppp->rx_pkt);
290 ppp->rx_pkt = NULL;
291 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
292 #if defined(CONFIG_NET_STATISTICS_PPP)
293 ppp->stats.drop++;
294 #endif
295 }
296
297 break;
298
299 case MODEM_PPP_RECEIVE_STATE_UNESCAPING:
300 if (net_pkt_write_u8(ppp->rx_pkt, (byte ^ MODEM_PPP_VALUE_ESCAPE)) < 0) {
301 LOG_WRN("Dropped PPP frame");
302 net_pkt_unref(ppp->rx_pkt);
303 ppp->rx_pkt = NULL;
304 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
305 #if defined(CONFIG_NET_STATISTICS_PPP)
306 ppp->stats.drop++;
307 #endif
308 break;
309 }
310
311 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_WRITING;
312 break;
313 }
314 }
315
316 #if CONFIG_MODEM_STATS
get_transmit_buf_length(struct modem_ppp * ppp)317 static uint32_t get_transmit_buf_length(struct modem_ppp *ppp)
318 {
319 return ring_buf_size_get(&ppp->transmit_rb);
320 }
321
advertise_transmit_buf_stats(struct modem_ppp * ppp)322 static void advertise_transmit_buf_stats(struct modem_ppp *ppp)
323 {
324 uint32_t length;
325
326 length = get_transmit_buf_length(ppp);
327 modem_stats_buffer_advertise_length(&ppp->transmit_buf_stats, length);
328 }
329
advertise_receive_buf_stats(struct modem_ppp * ppp,uint32_t length)330 static void advertise_receive_buf_stats(struct modem_ppp *ppp, uint32_t length)
331 {
332 modem_stats_buffer_advertise_length(&ppp->receive_buf_stats, length);
333 }
334 #endif
335
modem_ppp_pipe_callback(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)336 static void modem_ppp_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event,
337 void *user_data)
338 {
339 struct modem_ppp *ppp = (struct modem_ppp *)user_data;
340
341 switch (event) {
342 case MODEM_PIPE_EVENT_RECEIVE_READY:
343 k_work_submit(&ppp->process_work);
344 break;
345
346 case MODEM_PIPE_EVENT_OPENED:
347 case MODEM_PIPE_EVENT_TRANSMIT_IDLE:
348 k_work_submit(&ppp->send_work);
349 break;
350
351 default:
352 break;
353 }
354 }
355
modem_ppp_send_handler(struct k_work * item)356 static void modem_ppp_send_handler(struct k_work *item)
357 {
358 struct modem_ppp *ppp = CONTAINER_OF(item, struct modem_ppp, send_work);
359 uint8_t byte;
360 uint8_t *reserved;
361 uint32_t reserved_size;
362 int ret;
363
364 if (ppp->tx_pkt == NULL) {
365 ppp->tx_pkt = k_fifo_get(&ppp->tx_pkt_fifo, K_NO_WAIT);
366 }
367
368 if (ppp->tx_pkt != NULL) {
369 /* Initialize wrap */
370 if (ppp->transmit_state == MODEM_PPP_TRANSMIT_STATE_IDLE) {
371 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_SOF;
372 }
373
374 /* Fill transmit ring buffer */
375 while (ring_buf_space_get(&ppp->transmit_rb) > 0) {
376 byte = modem_ppp_wrap_net_pkt_byte(ppp);
377
378 ring_buf_put(&ppp->transmit_rb, &byte, 1);
379
380 if (ppp->transmit_state == MODEM_PPP_TRANSMIT_STATE_IDLE) {
381 net_pkt_unref(ppp->tx_pkt);
382 ppp->tx_pkt = k_fifo_get(&ppp->tx_pkt_fifo, K_NO_WAIT);
383 break;
384 }
385 }
386 }
387
388 #if CONFIG_MODEM_STATS
389 advertise_transmit_buf_stats(ppp);
390 #endif
391
392 while (!ring_buf_is_empty(&ppp->transmit_rb)) {
393 reserved_size = ring_buf_get_claim(&ppp->transmit_rb, &reserved, UINT32_MAX);
394
395 ret = modem_pipe_transmit(ppp->pipe, reserved, reserved_size);
396 if (ret < 0) {
397 ring_buf_get_finish(&ppp->transmit_rb, 0);
398 break;
399 }
400
401 ring_buf_get_finish(&ppp->transmit_rb, (uint32_t)ret);
402
403 if (ret < reserved_size) {
404 break;
405 }
406 }
407 }
408
modem_ppp_process_handler(struct k_work * item)409 static void modem_ppp_process_handler(struct k_work *item)
410 {
411 struct modem_ppp *ppp = CONTAINER_OF(item, struct modem_ppp, process_work);
412 int ret;
413
414 ret = modem_pipe_receive(ppp->pipe, ppp->receive_buf, ppp->buf_size);
415 if (ret < 1) {
416 return;
417 }
418
419 #if CONFIG_MODEM_STATS
420 advertise_receive_buf_stats(ppp, ret);
421 #endif
422
423 for (int i = 0; i < ret; i++) {
424 modem_ppp_process_received_byte(ppp, ppp->receive_buf[i]);
425 }
426
427 k_work_submit(&ppp->process_work);
428 }
429
modem_ppp_ppp_api_init(struct net_if * iface)430 static void modem_ppp_ppp_api_init(struct net_if *iface)
431 {
432 const struct device *dev = net_if_get_device(iface);
433 struct modem_ppp *ppp = (struct modem_ppp *)dev->data;
434
435 net_ppp_init(iface);
436 net_if_flag_set(iface, NET_IF_NO_AUTO_START);
437 net_if_carrier_off(iface);
438
439 if (ppp->init_iface != NULL) {
440 ppp->init_iface(iface);
441 }
442
443 ppp->iface = iface;
444 }
445
modem_ppp_ppp_api_start(const struct device * dev)446 static int modem_ppp_ppp_api_start(const struct device *dev)
447 {
448 return 0;
449 }
450
modem_ppp_ppp_api_stop(const struct device * dev)451 static int modem_ppp_ppp_api_stop(const struct device *dev)
452 {
453 return 0;
454 }
455
modem_ppp_ppp_api_send(const struct device * dev,struct net_pkt * pkt)456 static int modem_ppp_ppp_api_send(const struct device *dev, struct net_pkt *pkt)
457 {
458 struct modem_ppp *ppp = (struct modem_ppp *)dev->data;
459
460 if (atomic_test_bit(&ppp->state, MODEM_PPP_STATE_ATTACHED_BIT) == false) {
461 return -EPERM;
462 }
463
464 /* Validate packet protocol */
465 if ((net_pkt_is_ppp(pkt) == false) && (net_pkt_family(pkt) != AF_INET) &&
466 (net_pkt_family(pkt) != AF_INET6)) {
467 return -EPROTONOSUPPORT;
468 }
469
470 /* Validate packet data length */
471 if (((net_pkt_get_len(pkt) < 2) && (net_pkt_is_ppp(pkt) == true)) ||
472 ((net_pkt_get_len(pkt) < 1))) {
473 return -ENODATA;
474 }
475
476 net_pkt_ref(pkt);
477 k_fifo_put(&ppp->tx_pkt_fifo, pkt);
478 k_work_submit(&ppp->send_work);
479 return 0;
480 }
481
482 #if defined(CONFIG_NET_STATISTICS_PPP)
modem_ppp_ppp_get_stats(const struct device * dev)483 static struct net_stats_ppp *modem_ppp_ppp_get_stats(const struct device *dev)
484 {
485 struct modem_ppp *ppp = (struct modem_ppp *)dev->data;
486
487 return &ppp->stats;
488 }
489 #endif
490
491 #if CONFIG_MODEM_STATS
get_buf_size(struct modem_ppp * ppp)492 static uint32_t get_buf_size(struct modem_ppp *ppp)
493 {
494 return ppp->buf_size;
495 }
496
init_buf_stats(struct modem_ppp * ppp)497 static void init_buf_stats(struct modem_ppp *ppp)
498 {
499 char iface_name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE - sizeof("_xx")];
500 char name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE];
501 int ret;
502 uint32_t size;
503
504 ret = net_if_get_name(ppp->iface, iface_name, sizeof(iface_name));
505 if (ret < 0) {
506 snprintk(iface_name, sizeof(iface_name), "ppp");
507 }
508
509 size = get_buf_size(ppp);
510 snprintk(name, sizeof(name), "%s_rx", iface_name);
511 modem_stats_buffer_init(&ppp->receive_buf_stats, name, size);
512 snprintk(name, sizeof(name), "%s_tx", iface_name);
513 modem_stats_buffer_init(&ppp->transmit_buf_stats, name, size);
514 }
515 #endif
516
517 const struct ppp_api modem_ppp_ppp_api = {
518 .iface_api.init = modem_ppp_ppp_api_init,
519 .start = modem_ppp_ppp_api_start,
520 .stop = modem_ppp_ppp_api_stop,
521 .send = modem_ppp_ppp_api_send,
522 #if defined(CONFIG_NET_STATISTICS_PPP)
523 .get_stats = modem_ppp_ppp_get_stats,
524 #endif
525 };
526
modem_ppp_attach(struct modem_ppp * ppp,struct modem_pipe * pipe)527 int modem_ppp_attach(struct modem_ppp *ppp, struct modem_pipe *pipe)
528 {
529 if (atomic_test_bit(&ppp->state, MODEM_PPP_STATE_ATTACHED_BIT) == true) {
530 return 0;
531 }
532
533 ppp->pipe = pipe;
534 modem_pipe_attach(pipe, modem_ppp_pipe_callback, ppp);
535
536 atomic_set_bit(&ppp->state, MODEM_PPP_STATE_ATTACHED_BIT);
537 return 0;
538 }
539
modem_ppp_get_iface(struct modem_ppp * ppp)540 struct net_if *modem_ppp_get_iface(struct modem_ppp *ppp)
541 {
542 return ppp->iface;
543 }
544
modem_ppp_release(struct modem_ppp * ppp)545 void modem_ppp_release(struct modem_ppp *ppp)
546 {
547 struct k_work_sync sync;
548 struct net_pkt *pkt;
549
550 if (atomic_test_and_clear_bit(&ppp->state, MODEM_PPP_STATE_ATTACHED_BIT) == false) {
551 return;
552 }
553
554 modem_pipe_release(ppp->pipe);
555 k_work_cancel_sync(&ppp->send_work, &sync);
556 k_work_cancel_sync(&ppp->process_work, &sync);
557 ppp->pipe = NULL;
558 ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_SOF;
559
560 if (ppp->rx_pkt != NULL) {
561 net_pkt_unref(ppp->rx_pkt);
562 ppp->rx_pkt = NULL;
563 }
564
565 ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_IDLE;
566
567 if (ppp->tx_pkt != NULL) {
568 net_pkt_unref(ppp->tx_pkt);
569 ppp->tx_pkt = NULL;
570 }
571
572 while (1) {
573 pkt = k_fifo_get(&ppp->tx_pkt_fifo, K_NO_WAIT);
574 if (pkt == NULL) {
575 break;
576 }
577
578 net_pkt_unref(pkt);
579 }
580 }
581
modem_ppp_init_internal(const struct device * dev)582 int modem_ppp_init_internal(const struct device *dev)
583 {
584 struct modem_ppp *ppp = (struct modem_ppp *)dev->data;
585
586 atomic_set(&ppp->state, 0);
587 ring_buf_init(&ppp->transmit_rb, ppp->buf_size, ppp->transmit_buf);
588 k_work_init(&ppp->send_work, modem_ppp_send_handler);
589 k_work_init(&ppp->process_work, modem_ppp_process_handler);
590 k_fifo_init(&ppp->tx_pkt_fifo);
591
592 #if CONFIG_MODEM_STATS
593 init_buf_stats(ppp);
594 #endif
595 return 0;
596 }
597