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