1 /** @file
2  * @brief Modem context helper driver
3  *
4  * A modem context driver allowing application to handle all
5  * aspects of received protocol data.
6  */
7 
8 /*
9  * Copyright (c) 2019 Foundries.io
10  *
11  * SPDX-License-Identifier: Apache-2.0
12  */
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(modem_context, CONFIG_MODEM_LOG_LEVEL);
16 
17 #include <zephyr/kernel.h>
18 
19 #include "modem_context.h"
20 
21 static struct modem_context *contexts[CONFIG_MODEM_CONTEXT_MAX_NUM];
22 
modem_context_sprint_ip_addr(const struct sockaddr * addr,char * buf,size_t buf_size)23 int modem_context_sprint_ip_addr(const struct sockaddr *addr, char *buf, size_t buf_size)
24 {
25 	static const char unknown_str[] = "unk";
26 
27 	if (addr->sa_family == AF_INET6) {
28 		if (buf_size < NET_IPV6_ADDR_LEN) {
29 			return -ENOMEM;
30 		}
31 
32 		if (net_addr_ntop(AF_INET6, &net_sin6(addr)->sin6_addr,
33 					buf, buf_size) == NULL) {
34 			return -ENOMEM;
35 		}
36 		return 0;
37 	}
38 
39 	if (addr->sa_family == AF_INET) {
40 		if (buf_size < NET_IPV4_ADDR_LEN) {
41 			return -ENOMEM;
42 		}
43 		if (net_addr_ntop(AF_INET, &net_sin(addr)->sin_addr,
44 					buf, buf_size) == NULL) {
45 			return -ENOMEM;
46 		}
47 		return 0;
48 	}
49 
50 	LOG_ERR("Unknown IP address family:%d", addr->sa_family);
51 
52 	if (buf_size < sizeof(unknown_str)) {
53 		return -ENOMEM;
54 	}
55 	strcpy(buf, unknown_str);
56 	return 0;
57 }
58 
modem_context_get_addr_port(const struct sockaddr * addr,uint16_t * port)59 int modem_context_get_addr_port(const struct sockaddr *addr, uint16_t *port)
60 {
61 	if (!addr || !port) {
62 		return -EINVAL;
63 	}
64 
65 	if (addr->sa_family == AF_INET6) {
66 		*port = ntohs(net_sin6(addr)->sin6_port);
67 		return 0;
68 	} else if (addr->sa_family == AF_INET) {
69 		*port = ntohs(net_sin(addr)->sin_port);
70 		return 0;
71 	}
72 
73 	return -EPROTONOSUPPORT;
74 }
75 
76 /**
77  * @brief  Finds modem context which owns the iface device.
78  *
79  * @param  dev: device used by the modem iface.
80  *
81  * @retval Modem context or NULL.
82  */
modem_context_from_iface_dev(const struct device * dev)83 struct modem_context *modem_context_from_iface_dev(const struct device *dev)
84 {
85 	int i;
86 
87 	for (i = 0; i < ARRAY_SIZE(contexts); i++) {
88 		if (contexts[i] && contexts[i]->iface.dev == dev) {
89 			return contexts[i];
90 		}
91 	}
92 
93 	return NULL;
94 }
95 
96 /**
97  * @brief  Assign a modem context if there is free space.
98  *
99  * @note   Amount of stored modem contexts is determined by
100  *         CONFIG_MODEM_CONTEXT_MAX_NUM.
101  *
102  * @param  ctx: modem context to persist.
103  *
104  * @retval 0 if ok, < 0 if error.
105  */
modem_context_get(struct modem_context * ctx)106 static int modem_context_get(struct modem_context *ctx)
107 {
108 	int i;
109 
110 	for (i = 0; i < ARRAY_SIZE(contexts); i++) {
111 		if (!contexts[i]) {
112 			contexts[i] = ctx;
113 			return 0;
114 		}
115 	}
116 
117 	return -ENOMEM;
118 }
119 
modem_context_from_id(int id)120 struct modem_context *modem_context_from_id(int id)
121 {
122 	if (id >= 0 && id < ARRAY_SIZE(contexts)) {
123 		return contexts[id];
124 	} else {
125 		return NULL;
126 	}
127 }
128 
modem_context_register(struct modem_context * ctx)129 int modem_context_register(struct modem_context *ctx)
130 {
131 	if (!ctx) {
132 		return -EINVAL;
133 	}
134 
135 	return modem_context_get(ctx);
136 }
137