1 /*
2  * Copyright (c) 2019-2020 Foundries.io
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT u_blox_sara_r4
8 
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(modem_ublox_sara_r4, CONFIG_MODEM_LOG_LEVEL);
11 
12 #include <zephyr/kernel.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/device.h>
17 #include <zephyr/init.h>
18 #include <zephyr/posix/fcntl.h>
19 
20 #include <zephyr/net/net_if.h>
21 #include <zephyr/net/net_offload.h>
22 #include <zephyr/net/offloaded_netdev.h>
23 #include <zephyr/net/socket_offload.h>
24 
25 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
26 #include <stdio.h>
27 #endif
28 
29 #include "modem_context.h"
30 #include "modem_socket.h"
31 #include "modem_cmd_handler.h"
32 #include "modem_iface_uart.h"
33 
34 #if !defined(CONFIG_MODEM_UBLOX_SARA_R4_MANUAL_MCCMNO)
35 #define CONFIG_MODEM_UBLOX_SARA_R4_MANUAL_MCCMNO ""
36 #endif
37 
38 
39 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
40 #include "tls_internal.h"
41 #include <zephyr/net/tls_credentials.h>
42 #endif
43 
44 /* pin settings */
45 static const struct gpio_dt_spec power_gpio = GPIO_DT_SPEC_INST_GET(0, mdm_power_gpios);
46 #if DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
47 static const struct gpio_dt_spec reset_gpio = GPIO_DT_SPEC_INST_GET(0, mdm_reset_gpios);
48 #endif
49 #if DT_INST_NODE_HAS_PROP(0, mdm_vint_gpios)
50 static const struct gpio_dt_spec vint_gpio = GPIO_DT_SPEC_INST_GET(0, mdm_vint_gpios);
51 #endif
52 
53 #define MDM_UART_NODE			DT_INST_BUS(0)
54 #define MDM_UART_DEV			DEVICE_DT_GET(MDM_UART_NODE)
55 
56 #define MDM_RESET_NOT_ASSERTED		1
57 #define MDM_RESET_ASSERTED		0
58 
59 #define MDM_CMD_TIMEOUT			K_SECONDS(10)
60 #define MDM_DNS_TIMEOUT			K_SECONDS(70)
61 #define MDM_CMD_CONN_TIMEOUT		K_SECONDS(120)
62 #define MDM_REGISTRATION_TIMEOUT	K_SECONDS(180)
63 #define MDM_PROMPT_CMD_DELAY		K_MSEC(50)
64 
65 #define MDM_MAX_DATA_LENGTH		1024
66 #define MDM_RECV_MAX_BUF		30
67 #define MDM_RECV_BUF_SIZE		128
68 
69 #define MDM_MAX_SOCKETS			6
70 #define MDM_BASE_SOCKET_NUM		0
71 
72 #define MDM_NETWORK_RETRY_COUNT		3
73 #define MDM_WAIT_FOR_RSSI_COUNT		10
74 #define MDM_WAIT_FOR_RSSI_DELAY		K_SECONDS(2)
75 
76 #define MDM_MANUFACTURER_LENGTH		10
77 #define MDM_MODEL_LENGTH		16
78 #define MDM_REVISION_LENGTH		64
79 #define MDM_IMEI_LENGTH			16
80 #define MDM_IMSI_LENGTH			16
81 #define MDM_APN_LENGTH			32
82 #define MDM_MAX_CERT_LENGTH		8192
83 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
84 #define MDM_VARIANT_UBLOX_R4 4
85 #define MDM_VARIANT_UBLOX_U2 2
86 #endif
87 
88 NET_BUF_POOL_DEFINE(mdm_recv_pool, MDM_RECV_MAX_BUF, MDM_RECV_BUF_SIZE,
89 		    0, NULL);
90 
91 /* RX thread structures */
92 K_KERNEL_STACK_DEFINE(modem_rx_stack,
93 		      CONFIG_MODEM_UBLOX_SARA_R4_RX_STACK_SIZE);
94 struct k_thread modem_rx_thread;
95 
96 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
97 /* RX thread work queue */
98 K_KERNEL_STACK_DEFINE(modem_workq_stack,
99 		      CONFIG_MODEM_UBLOX_SARA_R4_RX_WORKQ_STACK_SIZE);
100 static struct k_work_q modem_workq;
101 #endif
102 
103 /* socket read callback data */
104 struct socket_read_data {
105 	char *recv_buf;
106 	size_t recv_buf_len;
107 	struct sockaddr *recv_addr;
108 	uint16_t recv_read_len;
109 };
110 
111 /* driver data */
112 struct modem_data {
113 	struct net_if *net_iface;
114 	uint8_t mac_addr[6];
115 
116 	/* modem interface */
117 	struct modem_iface_uart_data iface_data;
118 	uint8_t iface_rb_buf[MDM_MAX_DATA_LENGTH];
119 
120 	/* modem cmds */
121 	struct modem_cmd_handler_data cmd_handler_data;
122 	uint8_t cmd_match_buf[MDM_RECV_BUF_SIZE + 1];
123 
124 	/* socket data */
125 	struct modem_socket_config socket_config;
126 	struct modem_socket sockets[MDM_MAX_SOCKETS];
127 
128 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
129 	/* RSSI work */
130 	struct k_work_delayable rssi_query_work;
131 #endif
132 
133 	/* modem data */
134 	char mdm_manufacturer[MDM_MANUFACTURER_LENGTH];
135 	char mdm_model[MDM_MODEL_LENGTH];
136 	char mdm_revision[MDM_REVISION_LENGTH];
137 	char mdm_imei[MDM_IMEI_LENGTH];
138 	char mdm_imsi[MDM_IMSI_LENGTH];
139 	int mdm_rssi;
140 
141 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
142 	/* modem variant */
143 	int mdm_variant;
144 #endif
145 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
146 	/* APN */
147 	char mdm_apn[MDM_APN_LENGTH];
148 #endif
149 
150 	/* modem state */
151 	int ev_creg;
152 
153 	/* bytes written to socket in last transaction */
154 	int sock_written;
155 
156 	/* response semaphore */
157 	struct k_sem sem_response;
158 
159 	/* prompt semaphore */
160 	struct k_sem sem_prompt;
161 };
162 
163 static struct modem_data mdata;
164 static struct modem_context mctx;
165 
166 #if defined(CONFIG_DNS_RESOLVER)
167 static struct zsock_addrinfo result;
168 static struct sockaddr result_addr;
169 static char result_canonname[DNS_MAX_NAME_SIZE + 1];
170 #endif
171 
172 /* helper macro to keep readability */
173 #define ATOI(s_, value_, desc_) modem_atoi(s_, value_, desc_, __func__)
174 
175 /**
176  * @brief  Convert string to long integer, but handle errors
177  *
178  * @param  s: string with representation of integer number
179  * @param  err_value: on error return this value instead
180  * @param  desc: name the string being converted
181  * @param  func: function where this is called (typically __func__)
182  *
183  * @retval return integer conversion on success, or err_value on error
184  */
modem_atoi(const char * s,const int err_value,const char * desc,const char * func)185 static int modem_atoi(const char *s, const int err_value,
186 		      const char *desc, const char *func)
187 {
188 	int ret;
189 	char *endptr;
190 
191 	ret = (int)strtol(s, &endptr, 10);
192 	if (!endptr || *endptr != '\0') {
193 		LOG_ERR("bad %s '%s' in %s", s, desc,
194 			func);
195 		return err_value;
196 	}
197 
198 	return ret;
199 }
200 
201 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
202 
203 /* the list of SIM profiles. Global scope, so the app can change it */
204 const char *modem_sim_profiles =
205 	CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN_PROFILES;
206 
find_apn(char * apn,int apnlen,const char * profiles,const char * imsi)207 int find_apn(char *apn, int apnlen, const char *profiles, const char *imsi)
208 {
209 	int rc = -1;
210 
211 	/* try to find a match */
212 	char *s = strstr(profiles, imsi);
213 
214 	if (s) {
215 		char *eos;
216 
217 		/* find the assignment operator preceding the match */
218 		while (s >= profiles && !strchr("=", *s)) {
219 			s--;
220 		}
221 		/* find the apn preceding the assignment operator */
222 		while (s >= profiles && strchr(" =", *s)) {
223 			s--;
224 		}
225 
226 		/* mark end of apn string */
227 		eos = s+1;
228 
229 		/* find first character of the apn */
230 		while (s >= profiles && !strchr(" ,", *s)) {
231 			s--;
232 		}
233 		s++;
234 
235 		/* copy the key */
236 		if (s >= profiles) {
237 			int len = eos - s;
238 
239 			if (len < apnlen) {
240 				memcpy(apn, s, len);
241 				apn[len] = '\0';
242 				rc = 0;
243 			} else {
244 				LOG_ERR("buffer overflow");
245 			}
246 		}
247 	}
248 
249 	return rc;
250 }
251 
252 /* try to detect APN automatically, based on IMSI */
modem_detect_apn(const char * imsi)253 int modem_detect_apn(const char *imsi)
254 {
255 	int rc = -1;
256 
257 	if (imsi != NULL && strlen(imsi) >= 5) {
258 
259 		/* extract MMC and MNC from IMSI */
260 		char mmcmnc[6];
261 		*mmcmnc = 0;
262 		strncat(mmcmnc, imsi, sizeof(mmcmnc)-1);
263 
264 		/* try to find a matching IMSI, and assign the APN */
265 		rc = find_apn(mdata.mdm_apn,
266 			sizeof(mdata.mdm_apn),
267 			modem_sim_profiles,
268 			mmcmnc);
269 		if (rc < 0) {
270 			rc = find_apn(mdata.mdm_apn,
271 				sizeof(mdata.mdm_apn),
272 				modem_sim_profiles,
273 				"*");
274 		}
275 	}
276 
277 	if (rc == 0) {
278 		LOG_INF("Assign APN: \"%s\"", mdata.mdm_apn);
279 	}
280 
281 	return rc;
282 }
283 #endif
284 
285 /* Forward declaration */
286 MODEM_CMD_DEFINE(on_cmd_sockwrite);
287 
288 /* send binary data via the +USO[ST/WR] commands */
send_socket_data(void * obj,const struct msghdr * msg,k_timeout_t timeout)289 static ssize_t send_socket_data(void *obj,
290 				const struct msghdr *msg,
291 				k_timeout_t timeout)
292 {
293 	int ret;
294 	char send_buf[sizeof("AT+USO**=###,"
295 			     "!####.####.####.####.####.####.####.####!,"
296 			     "#####,#########\r\n")];
297 	uint16_t dst_port = 0U;
298 	struct modem_socket *sock = (struct modem_socket *)obj;
299 	const struct modem_cmd handler_cmds[] = {
300 		MODEM_CMD("+USOST: ", on_cmd_sockwrite, 2U, ","),
301 		MODEM_CMD("+USOWR: ", on_cmd_sockwrite, 2U, ","),
302 	};
303 	struct sockaddr *dst_addr = msg->msg_name;
304 	size_t buf_len = 0;
305 
306 	if (!sock) {
307 		return -EINVAL;
308 	}
309 
310 	for (int i = 0; i < msg->msg_iovlen; i++) {
311 		if (!msg->msg_iov[i].iov_base || msg->msg_iov[i].iov_len == 0) {
312 			errno = EINVAL;
313 			return -1;
314 		}
315 		buf_len += msg->msg_iov[i].iov_len;
316 	}
317 
318 	if (!sock->is_connected && sock->ip_proto != IPPROTO_UDP) {
319 		errno = ENOTCONN;
320 		return -1;
321 	}
322 
323 	if (!dst_addr && sock->ip_proto == IPPROTO_UDP) {
324 		dst_addr = &sock->dst;
325 	}
326 
327 	/*
328 	 * Binary and ASCII mode allows sending MDM_MAX_DATA_LENGTH bytes to
329 	 * the socket in one command
330 	 */
331 	if (buf_len > MDM_MAX_DATA_LENGTH) {
332 		if (sock->type == SOCK_DGRAM) {
333 			errno = EMSGSIZE;
334 			return -1;
335 		}
336 
337 		buf_len = MDM_MAX_DATA_LENGTH;
338 	}
339 
340 	/* The number of bytes written will be reported by the modem */
341 	mdata.sock_written = 0;
342 
343 	if (sock->ip_proto == IPPROTO_UDP) {
344 		char ip_str[NET_IPV6_ADDR_LEN];
345 
346 		ret = modem_context_sprint_ip_addr(dst_addr, ip_str, sizeof(ip_str));
347 		if (ret != 0) {
348 			LOG_ERR("Error formatting IP string %d", ret);
349 			goto exit;
350 		}
351 
352 		ret = modem_context_get_addr_port(dst_addr, &dst_port);
353 		if (ret != 0) {
354 			LOG_ERR("Error getting port from IP address %d", ret);
355 			goto exit;
356 		}
357 
358 		snprintk(send_buf, sizeof(send_buf),
359 			 "AT+USOST=%d,\"%s\",%u,%zu", sock->id,
360 			 ip_str,
361 			 dst_port, buf_len);
362 	} else {
363 		snprintk(send_buf, sizeof(send_buf), "AT+USOWR=%d,%zu",
364 			 sock->id, buf_len);
365 	}
366 
367 	k_sem_take(&mdata.cmd_handler_data.sem_tx_lock, K_FOREVER);
368 
369 	/* Reset prompt '@' semaphore */
370 	k_sem_reset(&mdata.sem_prompt);
371 
372 	ret = modem_cmd_send_nolock(&mctx.iface, &mctx.cmd_handler,
373 				    NULL, 0U, send_buf, NULL, K_NO_WAIT);
374 	if (ret < 0) {
375 		goto exit;
376 	}
377 
378 	/* set command handlers */
379 	ret = modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
380 					    handler_cmds,
381 					    ARRAY_SIZE(handler_cmds),
382 					    true);
383 	if (ret < 0) {
384 		goto exit;
385 	}
386 
387 	/* Wait for prompt '@' */
388 	ret = k_sem_take(&mdata.sem_prompt, K_SECONDS(1));
389 	if (ret != 0) {
390 		ret = -ETIMEDOUT;
391 		LOG_ERR("No @ prompt received");
392 		goto exit;
393 	}
394 
395 	/*
396 	 * The AT commands manual requires a 50 ms wait
397 	 * after '@' prompt if using AT+USOWR, but not
398 	 * if using AT+USOST. This if condition is matched with
399 	 * the command selection above.
400 	 */
401 	if (sock->ip_proto != IPPROTO_UDP) {
402 		k_sleep(MDM_PROMPT_CMD_DELAY);
403 	}
404 
405 	/* Reset response semaphore before sending data
406 	 * So that we are sure that we won't use a previously pending one
407 	 * And we won't miss the one that is going to be freed
408 	 */
409 	k_sem_reset(&mdata.sem_response);
410 
411 	/* Send data directly on modem iface */
412 	for (int i = 0; i < msg->msg_iovlen; i++) {
413 		int len = MIN(buf_len, msg->msg_iov[i].iov_len);
414 
415 		if (len == 0) {
416 			break;
417 		}
418 		mctx.iface.write(&mctx.iface, msg->msg_iov[i].iov_base, len);
419 		buf_len -= len;
420 	}
421 
422 	if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
423 		ret = 0;
424 		goto exit;
425 	}
426 	ret = k_sem_take(&mdata.sem_response, timeout);
427 
428 	if (ret == 0) {
429 		ret = modem_cmd_handler_get_error(&mdata.cmd_handler_data);
430 	} else if (ret == -EAGAIN) {
431 		ret = -ETIMEDOUT;
432 	}
433 
434 exit:
435 	/* unset handler commands and ignore any errors */
436 	(void)modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
437 					    NULL, 0U, false);
438 	k_sem_give(&mdata.cmd_handler_data.sem_tx_lock);
439 
440 	if (ret < 0) {
441 		return ret;
442 	}
443 
444 	return mdata.sock_written;
445 }
446 
447 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
448 /* send binary data via the +USO[ST/WR] commands */
send_cert(struct modem_socket * sock,struct modem_cmd * handler_cmds,size_t handler_cmds_len,const char * cert_data,size_t cert_len,int cert_type)449 static ssize_t send_cert(struct modem_socket *sock,
450 			 struct modem_cmd *handler_cmds,
451 			 size_t handler_cmds_len,
452 			 const char *cert_data, size_t cert_len,
453 			 int cert_type)
454 {
455 	int ret;
456 	char *filename = "ca";
457 	char send_buf[sizeof("AT+USECMNG=#,#,!####!,####\r\n")];
458 
459 	/* TODO support other cert types as well */
460 	if (cert_type != 0) {
461 		return -EINVAL;
462 	}
463 
464 	if (!sock) {
465 		return -EINVAL;
466 	}
467 
468 	__ASSERT_NO_MSG(cert_len <= MDM_MAX_CERT_LENGTH);
469 
470 	snprintk(send_buf, sizeof(send_buf),
471 		 "AT+USECMNG=0,%d,\"%s\",%d", cert_type, filename, cert_len);
472 
473 	k_sem_take(&mdata.cmd_handler_data.sem_tx_lock, K_FOREVER);
474 
475 	ret = modem_cmd_send_nolock(&mctx.iface, &mctx.cmd_handler,
476 				    NULL, 0U, send_buf, NULL, K_NO_WAIT);
477 	if (ret < 0) {
478 		goto exit;
479 	}
480 
481 	/* set command handlers */
482 	ret = modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
483 					    handler_cmds, handler_cmds_len,
484 					    true);
485 	if (ret < 0) {
486 		goto exit;
487 	}
488 
489 	/* slight pause per spec so that @ prompt is received */
490 	k_sleep(MDM_PROMPT_CMD_DELAY);
491 	mctx.iface.write(&mctx.iface, cert_data, cert_len);
492 
493 	k_sem_reset(&mdata.sem_response);
494 	ret = k_sem_take(&mdata.sem_response, K_MSEC(1000));
495 
496 	if (ret == 0) {
497 		ret = modem_cmd_handler_get_error(&mdata.cmd_handler_data);
498 	} else if (ret == -EAGAIN) {
499 		ret = -ETIMEDOUT;
500 	}
501 
502 exit:
503 	/* unset handler commands and ignore any errors */
504 	(void)modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
505 					    NULL, 0U, false);
506 	k_sem_give(&mdata.cmd_handler_data.sem_tx_lock);
507 
508 	return ret;
509 }
510 #endif
511 
512 /*
513  * Modem Response Command Handlers
514  */
515 
516 /* Handler: OK */
MODEM_CMD_DEFINE(on_cmd_ok)517 MODEM_CMD_DEFINE(on_cmd_ok)
518 {
519 	modem_cmd_handler_set_error(data, 0);
520 	k_sem_give(&mdata.sem_response);
521 	return 0;
522 }
523 
524 /* Handler: @ */
MODEM_CMD_DEFINE(on_prompt)525 MODEM_CMD_DEFINE(on_prompt)
526 {
527 	k_sem_give(&mdata.sem_prompt);
528 
529 	/* A direct cmd should return the number of byte processed.
530 	 * Therefore, here we always return 1
531 	 */
532 	return 1;
533 }
534 
535 /* Handler: ERROR */
MODEM_CMD_DEFINE(on_cmd_error)536 MODEM_CMD_DEFINE(on_cmd_error)
537 {
538 	modem_cmd_handler_set_error(data, -EIO);
539 	k_sem_give(&mdata.sem_response);
540 	return 0;
541 }
542 
543 /* Handler: +CME Error: <err>[0] */
MODEM_CMD_DEFINE(on_cmd_exterror)544 MODEM_CMD_DEFINE(on_cmd_exterror)
545 {
546 	/* TODO: map extended error codes to values */
547 	modem_cmd_handler_set_error(data, -EIO);
548 	k_sem_give(&mdata.sem_response);
549 	return 0;
550 }
551 
552 /*
553  * Modem Info Command Handlers
554  */
555 
556 /* Handler: <manufacturer> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_manufacturer)557 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_manufacturer)
558 {
559 	size_t out_len;
560 
561 	out_len = net_buf_linearize(mdata.mdm_manufacturer,
562 				    sizeof(mdata.mdm_manufacturer) - 1,
563 				    data->rx_buf, 0, len);
564 	mdata.mdm_manufacturer[out_len] = '\0';
565 	LOG_INF("Manufacturer: %s", mdata.mdm_manufacturer);
566 	return 0;
567 }
568 
569 /* Handler: <model> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_model)570 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_model)
571 {
572 	size_t out_len;
573 
574 	out_len = net_buf_linearize(mdata.mdm_model,
575 				    sizeof(mdata.mdm_model) - 1,
576 				    data->rx_buf, 0, len);
577 	mdata.mdm_model[out_len] = '\0';
578 	LOG_INF("Model: %s", mdata.mdm_model);
579 
580 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
581 	/* Set modem type */
582 	if (strstr(mdata.mdm_model, "R4")) {
583 		mdata.mdm_variant = MDM_VARIANT_UBLOX_R4;
584 	} else {
585 		if (strstr(mdata.mdm_model, "U2")) {
586 			mdata.mdm_variant = MDM_VARIANT_UBLOX_U2;
587 		}
588 	}
589 	LOG_INF("Variant: %d", mdata.mdm_variant);
590 #endif
591 
592 	return 0;
593 }
594 
595 /* Handler: <rev> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_revision)596 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_revision)
597 {
598 	size_t out_len;
599 
600 	out_len = net_buf_linearize(mdata.mdm_revision,
601 				    sizeof(mdata.mdm_revision) - 1,
602 				    data->rx_buf, 0, len);
603 	mdata.mdm_revision[out_len] = '\0';
604 	LOG_INF("Revision: %s", mdata.mdm_revision);
605 	return 0;
606 }
607 
608 /* Handler: <IMEI> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imei)609 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imei)
610 {
611 	size_t out_len;
612 
613 	out_len = net_buf_linearize(mdata.mdm_imei, sizeof(mdata.mdm_imei) - 1,
614 				    data->rx_buf, 0, len);
615 	mdata.mdm_imei[out_len] = '\0';
616 	LOG_INF("IMEI: %s", mdata.mdm_imei);
617 	return 0;
618 }
619 
620 /* Handler: <IMSI> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imsi)621 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imsi)
622 {
623 	size_t out_len;
624 
625 	out_len = net_buf_linearize(mdata.mdm_imsi, sizeof(mdata.mdm_imsi) - 1,
626 				    data->rx_buf, 0, len);
627 	mdata.mdm_imsi[out_len] = '\0';
628 	LOG_INF("IMSI: %s", mdata.mdm_imsi);
629 
630 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
631 	/* set the APN automatically */
632 	modem_detect_apn(mdata.mdm_imsi);
633 #endif
634 
635 	return 0;
636 }
637 
638 #if !defined(CONFIG_MODEM_UBLOX_SARA_U2)
639 /*
640  * Handler: +CESQ: <rxlev>[0],<ber>[1],<rscp>[2],<ecn0>[3],<rsrq>[4],<rsrp>[5]
641  */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_cesq)642 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_cesq)
643 {
644 	int rsrp, rxlev;
645 
646 	rsrp = ATOI(argv[5], 0, "rsrp");
647 	rxlev = ATOI(argv[0], 0, "rxlev");
648 	if (rsrp >= 0 && rsrp <= 97) {
649 		mdata.mdm_rssi = -140 + (rsrp - 1);
650 		LOG_INF("RSRP: %d", mdata.mdm_rssi);
651 	} else if (rxlev >= 0 && rxlev <= 63) {
652 		mdata.mdm_rssi = -110 + (rxlev - 1);
653 		LOG_INF("RSSI: %d", mdata.mdm_rssi);
654 	} else {
655 		mdata.mdm_rssi = -1000;
656 		LOG_INF("RSRP/RSSI not known");
657 	}
658 
659 	return 0;
660 }
661 #endif
662 
663 #if defined(CONFIG_MODEM_UBLOX_SARA_U2) \
664 	|| defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
665 /* Handler: +CSQ: <signal_power>[0],<qual>[1] */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_csq)666 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_csq)
667 {
668 	int rssi;
669 
670 	rssi = ATOI(argv[0], 0, "signal_power");
671 	if (rssi == 31) {
672 		mdata.mdm_rssi = -46;
673 	} else if (rssi >= 0 && rssi <= 31) {
674 		/* FIXME: This value depends on the RAT */
675 		mdata.mdm_rssi = -110 + ((rssi * 2) + 1);
676 	} else {
677 		mdata.mdm_rssi = -1000;
678 	}
679 
680 	LOG_INF("RSSI: %d", mdata.mdm_rssi);
681 	return 0;
682 }
683 #endif
684 
685 #if defined(CONFIG_MODEM_CELL_INFO)
unquoted_atoi(const char * s,int base)686 static int unquoted_atoi(const char *s, int base)
687 {
688 	if (*s == '"') {
689 		s++;
690 	}
691 
692 	return strtol(s, NULL, base);
693 }
694 
695 /*
696  * Handler: +COPS: <mode>[0],<format>[1],<oper>[2]
697  */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_cops)698 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_cops)
699 {
700 	if (argc >= 3) {
701 		mctx.data_operator = unquoted_atoi(argv[2], 10);
702 		LOG_INF("operator: %u",
703 			mctx.data_operator);
704 	}
705 
706 	return 0;
707 }
708 
709 /*
710  * Handler: +CEREG: <n>[0],<stat>[1],<tac>[2],<ci>[3],<AcT>[4]
711  */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_cereg)712 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_cereg)
713 {
714 	if (argc >= 4) {
715 		mctx.data_lac = unquoted_atoi(argv[2], 16);
716 		mctx.data_cellid = unquoted_atoi(argv[3], 16);
717 		LOG_INF("lac: %u, cellid: %u",
718 			mctx.data_lac,
719 			mctx.data_cellid);
720 	}
721 
722 	return 0;
723 }
724 
725 static const struct setup_cmd query_cellinfo_cmds[] = {
726 	SETUP_CMD_NOHANDLE("AT+CEREG=2"),
727 	SETUP_CMD("AT+CEREG?", "", on_cmd_atcmdinfo_cereg, 5U, ","),
728 	SETUP_CMD_NOHANDLE("AT+COPS=3,2"),
729 	SETUP_CMD("AT+COPS?", "", on_cmd_atcmdinfo_cops, 3U, ","),
730 };
731 #endif /* CONFIG_MODEM_CELL_INFO */
732 
733 /*
734  * Modem Socket Command Handlers
735  */
736 
737 /* Handler: +USOCR: <socket_id>[0] */
MODEM_CMD_DEFINE(on_cmd_sockcreate)738 MODEM_CMD_DEFINE(on_cmd_sockcreate)
739 {
740 	struct modem_socket *sock = NULL;
741 	int id;
742 
743 	/* look up new socket by special id */
744 	sock = modem_socket_from_newid(&mdata.socket_config);
745 	if (sock) {
746 		id = ATOI(argv[0], -1, "socket_id");
747 
748 		/* on error give up modem socket */
749 		if (modem_socket_id_assign(&mdata.socket_config, sock, id) < 0) {
750 			modem_socket_put(&mdata.socket_config, sock->sock_fd);
751 		}
752 	}
753 
754 	/* don't give back semaphore -- OK to follow */
755 	return 0;
756 }
757 
758 /* Handler: +USO[WR|ST]: <socket_id>[0],<length>[1] */
MODEM_CMD_DEFINE(on_cmd_sockwrite)759 MODEM_CMD_DEFINE(on_cmd_sockwrite)
760 {
761 	mdata.sock_written = ATOI(argv[1], 0, "length");
762 	LOG_DBG("bytes written: %d", mdata.sock_written);
763 	return 0;
764 }
765 
766 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
767 /* Handler: +USECMNG: 0,<type>[0],<internal_name>[1],<md5_string>[2] */
MODEM_CMD_DEFINE(on_cmd_cert_write)768 MODEM_CMD_DEFINE(on_cmd_cert_write)
769 {
770 	LOG_DBG("cert md5: %s", argv[2]);
771 	return 0;
772 }
773 #endif
774 
775 /* Common code for +USOR[D|F]: "<data>" */
on_cmd_sockread_common(int socket_id,struct modem_cmd_handler_data * data,int socket_data_length,uint16_t len)776 static int on_cmd_sockread_common(int socket_id,
777 				  struct modem_cmd_handler_data *data,
778 				  int socket_data_length, uint16_t len)
779 {
780 	struct modem_socket *sock = NULL;
781 	struct socket_read_data *sock_data;
782 	int ret;
783 
784 	if (!len) {
785 		LOG_ERR("Short +USOR[D|F] value.  Aborting!");
786 		return -EAGAIN;
787 	}
788 
789 	/*
790 	 * make sure we still have buf data and next char in the buffer is a
791 	 * quote.
792 	 */
793 	if (!data->rx_buf || *data->rx_buf->data != '\"') {
794 		LOG_ERR("Incorrect format! Ignoring data!");
795 		return -EINVAL;
796 	}
797 
798 	/* zero length */
799 	if (socket_data_length <= 0) {
800 		LOG_ERR("Length problem (%d).  Aborting!", socket_data_length);
801 		return -EAGAIN;
802 	}
803 
804 	/* check to make sure we have all of the data (minus quotes) */
805 	if ((net_buf_frags_len(data->rx_buf) - 2) < socket_data_length) {
806 		LOG_DBG("Not enough data -- wait!");
807 		return -EAGAIN;
808 	}
809 
810 	/* skip quote */
811 	len--;
812 	net_buf_pull_u8(data->rx_buf);
813 	if (!data->rx_buf->len) {
814 		data->rx_buf = net_buf_frag_del(NULL, data->rx_buf);
815 	}
816 
817 	sock = modem_socket_from_id(&mdata.socket_config, socket_id);
818 	if (!sock) {
819 		LOG_ERR("Socket not found! (%d)", socket_id);
820 		ret = -EINVAL;
821 		goto exit;
822 	}
823 
824 	sock_data = (struct socket_read_data *)sock->data;
825 	if (!sock_data) {
826 		LOG_ERR("Socket data not found! Skip handling (%d)", socket_id);
827 		ret = -EINVAL;
828 		goto exit;
829 	}
830 
831 	ret = net_buf_linearize(sock_data->recv_buf, sock_data->recv_buf_len,
832 				data->rx_buf, 0, (uint16_t)socket_data_length);
833 	data->rx_buf = net_buf_skip(data->rx_buf, ret);
834 	sock_data->recv_read_len = ret;
835 	if (ret != socket_data_length) {
836 		LOG_ERR("Total copied data is different then received data!"
837 			" copied:%d vs. received:%d", ret, socket_data_length);
838 		ret = -EINVAL;
839 	}
840 
841 exit:
842 	/* remove packet from list (ignore errors) */
843 	(void)modem_socket_packet_size_update(&mdata.socket_config, sock,
844 					      -socket_data_length);
845 
846 	/* don't give back semaphore -- OK to follow */
847 	return ret;
848 }
849 
850 /*
851  * Handler: +USORF: <socket_id>[0],<remote_ip_addr>[1],<remote_port>[2],
852  *          <length>[3],"<data>"
853 */
MODEM_CMD_DEFINE(on_cmd_sockreadfrom)854 MODEM_CMD_DEFINE(on_cmd_sockreadfrom)
855 {
856 	/* TODO: handle remote_ip_addr */
857 
858 	return on_cmd_sockread_common(ATOI(argv[0], 0, "socket_id"), data,
859 				      ATOI(argv[3], 0, "length"), len);
860 }
861 
862 /* Handler: +USORD: <socket_id>[0],<length>[1],"<data>" */
MODEM_CMD_DEFINE(on_cmd_sockread)863 MODEM_CMD_DEFINE(on_cmd_sockread)
864 {
865 	return on_cmd_sockread_common(ATOI(argv[0], 0, "socket_id"), data,
866 				      ATOI(argv[1], 0, "length"), len);
867 }
868 
869 #if defined(CONFIG_DNS_RESOLVER)
870 /* Handler: +UDNSRN: "<resolved_ip_address>"[0], "<resolved_ip_address>"[1] */
MODEM_CMD_DEFINE(on_cmd_dns)871 MODEM_CMD_DEFINE(on_cmd_dns)
872 {
873 	/* chop off end quote */
874 	argv[0][strlen(argv[0]) - 1] = '\0';
875 
876 	/* FIXME: Hard-code DNS on SARA-R4 to return IPv4 */
877 	result_addr.sa_family = AF_INET;
878 	/* skip beginning quote when parsing */
879 	(void)net_addr_pton(result.ai_family, &argv[0][1],
880 			    &((struct sockaddr_in *)&result_addr)->sin_addr);
881 	return 0;
882 }
883 #endif
884 
885 /*
886  * MODEM UNSOLICITED NOTIFICATION HANDLERS
887  */
888 
889 /* Handler: +UUSOCL: <socket_id>[0] */
MODEM_CMD_DEFINE(on_cmd_socknotifyclose)890 MODEM_CMD_DEFINE(on_cmd_socknotifyclose)
891 {
892 	struct modem_socket *sock;
893 
894 	sock = modem_socket_from_id(&mdata.socket_config,
895 				    ATOI(argv[0], 0, "socket_id"));
896 	if (sock) {
897 		sock->is_connected = false;
898 	}
899 
900 	return 0;
901 }
902 
903 /* Handler: +UUSOR[D|F]: <socket_id>[0],<length>[1] */
MODEM_CMD_DEFINE(on_cmd_socknotifydata)904 MODEM_CMD_DEFINE(on_cmd_socknotifydata)
905 {
906 	int ret, socket_id, new_total;
907 	struct modem_socket *sock;
908 
909 	socket_id = ATOI(argv[0], 0, "socket_id");
910 	new_total = ATOI(argv[1], 0, "length");
911 	sock = modem_socket_from_id(&mdata.socket_config, socket_id);
912 	if (!sock) {
913 		return 0;
914 	}
915 
916 	ret = modem_socket_packet_size_update(&mdata.socket_config, sock,
917 					      new_total);
918 	if (ret < 0) {
919 		LOG_ERR("socket_id:%d left_bytes:%d err: %d", socket_id,
920 			new_total, ret);
921 	}
922 
923 	if (new_total > 0) {
924 		modem_socket_data_ready(&mdata.socket_config, sock);
925 	}
926 
927 	return 0;
928 }
929 
930 /* Handler: +CREG: <stat>[0] */
MODEM_CMD_DEFINE(on_cmd_socknotifycreg)931 MODEM_CMD_DEFINE(on_cmd_socknotifycreg)
932 {
933 	mdata.ev_creg = ATOI(argv[0], 0, "stat");
934 	LOG_DBG("CREG:%d", mdata.ev_creg);
935 	return 0;
936 }
937 
938 /* RX thread */
modem_rx(void * p1,void * p2,void * p3)939 static void modem_rx(void *p1, void *p2, void *p3)
940 {
941 	ARG_UNUSED(p1);
942 	ARG_UNUSED(p2);
943 	ARG_UNUSED(p3);
944 
945 	while (true) {
946 		/* wait for incoming data */
947 		modem_iface_uart_rx_wait(&mctx.iface, K_FOREVER);
948 
949 		modem_cmd_handler_process(&mctx.cmd_handler, &mctx.iface);
950 
951 		/* give up time if we have a solid stream of data */
952 		k_yield();
953 	}
954 }
955 
pin_init(void)956 static int pin_init(void)
957 {
958 	LOG_INF("Setting Modem Pins");
959 
960 #if DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
961 	LOG_DBG("MDM_RESET_PIN -> NOT_ASSERTED");
962 	gpio_pin_set_dt(&reset_gpio, MDM_RESET_NOT_ASSERTED);
963 #endif
964 
965 	LOG_DBG("MDM_POWER_PIN -> ENABLE");
966 	gpio_pin_set_dt(&power_gpio, 1);
967 	k_sleep(K_SECONDS(4));
968 
969 	LOG_DBG("MDM_POWER_PIN -> DISABLE");
970 	gpio_pin_set_dt(&power_gpio, 0);
971 #if defined(CONFIG_MODEM_UBLOX_SARA_U2)
972 	k_sleep(K_SECONDS(1));
973 #else
974 	k_sleep(K_SECONDS(4));
975 #endif
976 	LOG_DBG("MDM_POWER_PIN -> ENABLE");
977 	gpio_pin_set_dt(&power_gpio, 1);
978 	k_sleep(K_SECONDS(1));
979 
980 	/* make sure module is powered off */
981 #if DT_INST_NODE_HAS_PROP(0, mdm_vint_gpios)
982 	LOG_DBG("Waiting for MDM_VINT_PIN = 0");
983 
984 	while (gpio_pin_get_dt(&vint_gpio) > 0) {
985 #if defined(CONFIG_MODEM_UBLOX_SARA_U2)
986 		/* try to power off again */
987 		LOG_DBG("MDM_POWER_PIN -> DISABLE");
988 		gpio_pin_set_dt(&power_gpio, 0);
989 		k_sleep(K_SECONDS(1));
990 		LOG_DBG("MDM_POWER_PIN -> ENABLE");
991 		gpio_pin_set_dt(&power_gpio, 1);
992 #endif
993 		k_sleep(K_MSEC(100));
994 	}
995 #else
996 	k_sleep(K_SECONDS(8));
997 #endif
998 
999 	LOG_DBG("MDM_POWER_PIN -> DISABLE");
1000 
1001 	unsigned int irq_lock_key = irq_lock();
1002 
1003 	gpio_pin_set_dt(&power_gpio, 0);
1004 #if defined(CONFIG_MODEM_UBLOX_SARA_U2)
1005 	k_usleep(50);		/* 50-80 microseconds */
1006 #else
1007 	k_sleep(K_SECONDS(1));
1008 #endif
1009 	gpio_pin_set_dt(&power_gpio, 1);
1010 
1011 	irq_unlock(irq_lock_key);
1012 
1013 	LOG_DBG("MDM_POWER_PIN -> ENABLE");
1014 
1015 #if DT_INST_NODE_HAS_PROP(0, mdm_vint_gpios)
1016 	LOG_DBG("Waiting for MDM_VINT_PIN = 1");
1017 	do {
1018 		k_sleep(K_MSEC(100));
1019 	} while (gpio_pin_get_dt(&vint_gpio) == 0);
1020 #else
1021 	k_sleep(K_SECONDS(10));
1022 #endif
1023 
1024 	gpio_pin_configure_dt(&power_gpio, GPIO_INPUT);
1025 
1026 	LOG_INF("... Done!");
1027 
1028 	return 0;
1029 }
1030 
1031 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
modem_rssi_query_work(struct k_work * work)1032 static void modem_rssi_query_work(struct k_work *work)
1033 {
1034 	static const struct modem_cmd cmds[] = {
1035 		  MODEM_CMD("+CSQ: ", on_cmd_atcmdinfo_rssi_csq, 2U, ","),
1036 		  MODEM_CMD("+CESQ: ", on_cmd_atcmdinfo_rssi_cesq, 6U, ","),
1037 	};
1038 	const char *send_cmd_u2 = "AT+CSQ";
1039 	const char *send_cmd_r4 = "AT+CESQ";
1040 	int ret;
1041 
1042 	/* choose cmd according to variant */
1043 	const char *send_cmd = send_cmd_r4;
1044 
1045 	if (mdata.mdm_variant == MDM_VARIANT_UBLOX_U2) {
1046 		send_cmd = send_cmd_u2;
1047 	}
1048 
1049 	/* query modem RSSI */
1050 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1051 		cmds, ARRAY_SIZE(cmds),
1052 		send_cmd,
1053 		&mdata.sem_response,
1054 		MDM_CMD_TIMEOUT);
1055 	if (ret < 0) {
1056 		LOG_ERR("AT+C[E]SQ ret:%d", ret);
1057 	}
1058 
1059 #if defined(CONFIG_MODEM_CELL_INFO)
1060 	/* query cell info */
1061 	ret = modem_cmd_handler_setup_cmds_nolock(&mctx.iface,
1062 						  &mctx.cmd_handler,
1063 						  query_cellinfo_cmds,
1064 						  ARRAY_SIZE(query_cellinfo_cmds),
1065 						  &mdata.sem_response,
1066 						  MDM_CMD_TIMEOUT);
1067 	if (ret < 0) {
1068 		LOG_WRN("modem query for cell info returned %d", ret);
1069 	}
1070 #endif
1071 
1072 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
1073 	/* re-start RSSI query work */
1074 	if (work) {
1075 		k_work_reschedule_for_queue(
1076 			&modem_workq, &mdata.rssi_query_work,
1077 			K_SECONDS(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK_PERIOD));
1078 	}
1079 #endif
1080 }
1081 #else
modem_rssi_query_work(struct k_work * work)1082 static void modem_rssi_query_work(struct k_work *work)
1083 {
1084 	static const struct modem_cmd cmd =
1085 #if defined(CONFIG_MODEM_UBLOX_SARA_U2)
1086 		MODEM_CMD("+CSQ: ", on_cmd_atcmdinfo_rssi_csq, 2U, ",");
1087 	static char *send_cmd = "AT+CSQ";
1088 #else
1089 		MODEM_CMD("+CESQ: ", on_cmd_atcmdinfo_rssi_cesq, 6U, ",");
1090 	static char *send_cmd = "AT+CESQ";
1091 #endif
1092 	int ret;
1093 
1094 	/* query modem RSSI */
1095 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1096 			     &cmd, 1U, send_cmd, &mdata.sem_response,
1097 			     MDM_CMD_TIMEOUT);
1098 	if (ret < 0) {
1099 		LOG_ERR("AT+C[E]SQ ret:%d", ret);
1100 	}
1101 
1102 #if defined(CONFIG_MODEM_CELL_INFO)
1103 	/* query cell info */
1104 	ret = modem_cmd_handler_setup_cmds_nolock(&mctx.iface,
1105 						  &mctx.cmd_handler,
1106 						  query_cellinfo_cmds,
1107 						  ARRAY_SIZE(query_cellinfo_cmds),
1108 						  &mdata.sem_response,
1109 						  MDM_CMD_TIMEOUT);
1110 	if (ret < 0) {
1111 		LOG_WRN("modem query for cell info returned %d", ret);
1112 	}
1113 #endif
1114 
1115 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
1116 	/* re-start RSSI query work */
1117 	if (work) {
1118 		k_work_reschedule_for_queue(
1119 			&modem_workq, &mdata.rssi_query_work,
1120 			K_SECONDS(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK_PERIOD));
1121 	}
1122 #endif
1123 }
1124 #endif
1125 
modem_reset(void)1126 static void modem_reset(void)
1127 {
1128 	int ret = 0, retry_count = 0, counter = 0;
1129 	static const struct setup_cmd setup_cmds[] = {
1130 		/* turn off echo */
1131 		SETUP_CMD_NOHANDLE("ATE0"),
1132 		/* stop functionality */
1133 		SETUP_CMD_NOHANDLE("AT+CFUN=0"),
1134 		/* extended error numbers */
1135 		SETUP_CMD_NOHANDLE("AT+CMEE=1"),
1136 #if defined(CONFIG_BOARD_PARTICLE_BORON)
1137 		/* use external SIM */
1138 		SETUP_CMD_NOHANDLE("AT+UGPIOC=23,0,0"),
1139 #endif
1140 #if defined(CONFIG_MODEM_UBLOX_SARA_R4_NET_STATUS_PIN)
1141 		/* enable the network status indication */
1142 		SETUP_CMD_NOHANDLE("AT+UGPIOC="
1143 			STRINGIFY(CONFIG_MODEM_UBLOX_SARA_R4_NET_STATUS_PIN)
1144 			",2"),
1145 #endif
1146 		/* UNC messages for registration */
1147 		SETUP_CMD_NOHANDLE("AT+CREG=1"),
1148 		/* query modem info */
1149 		SETUP_CMD("AT+CGMI", "", on_cmd_atcmdinfo_manufacturer, 0U, ""),
1150 		SETUP_CMD("AT+CGMM", "", on_cmd_atcmdinfo_model, 0U, ""),
1151 		SETUP_CMD("AT+CGMR", "", on_cmd_atcmdinfo_revision, 0U, ""),
1152 		SETUP_CMD("AT+CGSN", "", on_cmd_atcmdinfo_imei, 0U, ""),
1153 		SETUP_CMD("AT+CIMI", "", on_cmd_atcmdinfo_imsi, 0U, ""),
1154 #if !defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
1155 		/* setup PDP context definition */
1156 		SETUP_CMD_NOHANDLE("AT+CGDCONT=1,\"IP\",\""
1157 					CONFIG_MODEM_UBLOX_SARA_R4_APN "\""),
1158 		/* start functionality */
1159 		SETUP_CMD_NOHANDLE("AT+CFUN=1"),
1160 #endif
1161 	};
1162 
1163 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
1164 	static const struct setup_cmd post_setup_cmds_u2[] = {
1165 #if !defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
1166 		/* set the APN */
1167 		SETUP_CMD_NOHANDLE("AT+UPSD=0,1,\""
1168 				CONFIG_MODEM_UBLOX_SARA_R4_APN "\""),
1169 #endif
1170 		/* set dynamic IP */
1171 		SETUP_CMD_NOHANDLE("AT+UPSD=0,7,\"0.0.0.0\""),
1172 		/* activate the GPRS connection */
1173 		SETUP_CMD_NOHANDLE("AT+UPSDA=0,3"),
1174 	};
1175 #endif
1176 
1177 	static const struct setup_cmd post_setup_cmds[] = {
1178 #if defined(CONFIG_MODEM_UBLOX_SARA_U2)
1179 		/* set the APN */
1180 		SETUP_CMD_NOHANDLE("AT+UPSD=0,1,\""
1181 				CONFIG_MODEM_UBLOX_SARA_R4_APN "\""),
1182 		/* set dynamic IP */
1183 		SETUP_CMD_NOHANDLE("AT+UPSD=0,7,\"0.0.0.0\""),
1184 		/* activate the GPRS connection */
1185 		SETUP_CMD_NOHANDLE("AT+UPSDA=0,3"),
1186 #else
1187 		/* activate the PDP context */
1188 		SETUP_CMD_NOHANDLE("AT+CGACT=1,1"),
1189 #endif
1190 	};
1191 
1192 restart:
1193 
1194 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
1195 	mdata.mdm_apn[0] = '\0';
1196 	strncat(mdata.mdm_apn,
1197 		CONFIG_MODEM_UBLOX_SARA_R4_APN,
1198 		sizeof(mdata.mdm_apn)-1);
1199 #endif
1200 
1201 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
1202 	/* stop RSSI delay work */
1203 	k_work_cancel_delayable(&mdata.rssi_query_work);
1204 #endif
1205 
1206 	pin_init();
1207 
1208 	LOG_INF("Waiting for modem to respond");
1209 
1210 	/* Give the modem a while to start responding to simple 'AT' commands.
1211 	 * Also wait for CSPS=1 or RRCSTATE=1 notification
1212 	 */
1213 	ret = -1;
1214 	while (counter++ < 50 && ret < 0) {
1215 		k_sleep(K_SECONDS(2));
1216 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1217 				     NULL, 0, "AT", &mdata.sem_response,
1218 				     MDM_CMD_TIMEOUT);
1219 		if (ret < 0 && ret != -ETIMEDOUT) {
1220 			break;
1221 		}
1222 	}
1223 
1224 	if (ret < 0) {
1225 		LOG_ERR("MODEM WAIT LOOP ERROR: %d", ret);
1226 		goto error;
1227 	}
1228 
1229 	ret = modem_cmd_handler_setup_cmds(&mctx.iface, &mctx.cmd_handler,
1230 					   setup_cmds, ARRAY_SIZE(setup_cmds),
1231 					   &mdata.sem_response,
1232 					   MDM_REGISTRATION_TIMEOUT);
1233 	if (ret < 0) {
1234 		goto error;
1235 	}
1236 
1237 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
1238 	/* autodetect APN from IMSI */
1239 	char cmd[sizeof("AT+CGDCONT=1,\"IP\",\"\"")+MDM_APN_LENGTH];
1240 
1241 	snprintk(cmd, sizeof(cmd), "AT+CGDCONT=1,\"IP\",\"%s\"", mdata.mdm_apn);
1242 
1243 	/* setup PDP context definition */
1244 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1245 		NULL, 0,
1246 		(const char *)cmd,
1247 		&mdata.sem_response,
1248 		MDM_REGISTRATION_TIMEOUT);
1249 
1250 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1251 		NULL, 0,
1252 		"AT+CFUN=1",
1253 		&mdata.sem_response,
1254 		MDM_REGISTRATION_TIMEOUT);
1255 #endif
1256 
1257 	if (strlen(CONFIG_MODEM_UBLOX_SARA_R4_MANUAL_MCCMNO) > 0) {
1258 		/* use manual MCC/MNO entry */
1259 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1260 				     NULL, 0,
1261 				     "AT+COPS=1,2,\""
1262 					CONFIG_MODEM_UBLOX_SARA_R4_MANUAL_MCCMNO
1263 					"\"",
1264 				     &mdata.sem_response,
1265 				     MDM_REGISTRATION_TIMEOUT);
1266 	} else {
1267 		/* register operator automatically */
1268 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1269 				     NULL, 0, "AT+COPS=0,0",
1270 				     &mdata.sem_response,
1271 				     MDM_REGISTRATION_TIMEOUT);
1272 	}
1273 
1274 	if (ret < 0) {
1275 		LOG_ERR("AT+COPS ret:%d", ret);
1276 		goto error;
1277 	}
1278 
1279 	LOG_INF("Waiting for network");
1280 
1281 	/*
1282 	 * TODO: A lot of this should be setup as a 3GPP module to handle
1283 	 * basic connection to the network commands / polling
1284 	 */
1285 
1286 	/* wait for +CREG: 1(normal) or 5(roaming) */
1287 	counter = 0;
1288 	while (counter++ < 40 && mdata.ev_creg != 1 && mdata.ev_creg != 5) {
1289 		if (counter == 20) {
1290 			LOG_WRN("Force restart of RF functionality");
1291 
1292 			/* Disable RF temporarily */
1293 			ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1294 				NULL, 0, "AT+CFUN=0", &mdata.sem_response,
1295 				MDM_CMD_TIMEOUT);
1296 
1297 			k_sleep(K_SECONDS(1));
1298 
1299 			/* Enable RF */
1300 			ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1301 				NULL, 0, "AT+CFUN=1", &mdata.sem_response,
1302 				MDM_CMD_TIMEOUT);
1303 		}
1304 
1305 		k_sleep(K_SECONDS(1));
1306 	}
1307 
1308 	/* query modem RSSI */
1309 	modem_rssi_query_work(NULL);
1310 	k_sleep(MDM_WAIT_FOR_RSSI_DELAY);
1311 
1312 	counter = 0;
1313 	/* wait for RSSI < 0 and > -1000 */
1314 	while (counter++ < MDM_WAIT_FOR_RSSI_COUNT &&
1315 	       (mdata.mdm_rssi >= 0 ||
1316 		mdata.mdm_rssi <= -1000)) {
1317 		modem_rssi_query_work(NULL);
1318 		k_sleep(MDM_WAIT_FOR_RSSI_DELAY);
1319 	}
1320 
1321 	if (mdata.mdm_rssi >= 0 || mdata.mdm_rssi <= -1000) {
1322 		retry_count++;
1323 		if (retry_count >= MDM_NETWORK_RETRY_COUNT) {
1324 			LOG_ERR("Failed network init.  Too many attempts!");
1325 			ret = -ENETUNREACH;
1326 			goto error;
1327 		}
1328 
1329 		LOG_ERR("Failed network init.  Restarting process.");
1330 		goto restart;
1331 	}
1332 
1333 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
1334 	if (mdata.mdm_variant == MDM_VARIANT_UBLOX_U2) {
1335 
1336 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_APN)
1337 		/* setup PDP context definition */
1338 		char cmd[sizeof("AT+UPSD=0,1,\"%s\"")+MDM_APN_LENGTH];
1339 
1340 		snprintk(cmd, sizeof(cmd), "AT+UPSD=0,1,\"%s\"", mdata.mdm_apn);
1341 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1342 			NULL, 0,
1343 			(const char *)cmd,
1344 			&mdata.sem_response,
1345 			MDM_REGISTRATION_TIMEOUT);
1346 #endif
1347 		ret = modem_cmd_handler_setup_cmds(&mctx.iface,
1348 			&mctx.cmd_handler,
1349 			post_setup_cmds_u2,
1350 			ARRAY_SIZE(post_setup_cmds_u2),
1351 			&mdata.sem_response,
1352 			MDM_REGISTRATION_TIMEOUT);
1353 	} else {
1354 #endif
1355 		ret = modem_cmd_handler_setup_cmds(&mctx.iface,
1356 					   &mctx.cmd_handler,
1357 					   post_setup_cmds,
1358 					   ARRAY_SIZE(post_setup_cmds),
1359 					   &mdata.sem_response,
1360 					   MDM_REGISTRATION_TIMEOUT);
1361 #if defined(CONFIG_MODEM_UBLOX_SARA_AUTODETECT_VARIANT)
1362 	}
1363 #endif
1364 	if (ret < 0) {
1365 		goto error;
1366 	}
1367 
1368 	LOG_INF("Network is ready.");
1369 
1370 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
1371 	/* start RSSI query */
1372 	k_work_reschedule_for_queue(
1373 		&modem_workq, &mdata.rssi_query_work,
1374 		K_SECONDS(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK_PERIOD));
1375 #endif
1376 
1377 error:
1378 	return;
1379 }
1380 
1381 /*
1382  * generic socket creation function
1383  * which can be called in bind() or connect()
1384  */
create_socket(struct modem_socket * sock,const struct sockaddr * addr)1385 static int create_socket(struct modem_socket *sock, const struct sockaddr *addr)
1386 {
1387 	int ret;
1388 	static const struct modem_cmd cmd =
1389 		MODEM_CMD("+USOCR: ", on_cmd_sockcreate, 1U, "");
1390 	char buf[sizeof("AT+USOCR=#,#####\r")];
1391 	uint16_t local_port = 0U, proto = 6U;
1392 
1393 	if (addr) {
1394 		if (addr->sa_family == AF_INET6) {
1395 			local_port = ntohs(net_sin6(addr)->sin6_port);
1396 		} else if (addr->sa_family == AF_INET) {
1397 			local_port = ntohs(net_sin(addr)->sin_port);
1398 		}
1399 	}
1400 
1401 	if (sock->ip_proto == IPPROTO_UDP) {
1402 		proto = 17U;
1403 	}
1404 
1405 	if (local_port > 0U) {
1406 		snprintk(buf, sizeof(buf), "AT+USOCR=%d,%u", proto, local_port);
1407 	} else {
1408 		snprintk(buf, sizeof(buf), "AT+USOCR=%d", proto);
1409 	}
1410 
1411 	/* create socket */
1412 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1413 			     &cmd, 1U, buf,
1414 			     &mdata.sem_response, MDM_CMD_TIMEOUT);
1415 	if (ret < 0) {
1416 		goto error;
1417 	}
1418 
1419 	if (sock->ip_proto == IPPROTO_TLS_1_2) {
1420 		char atbuf[sizeof("AT+USECPRF=#,#,#######\r")];
1421 
1422 		/* Enable socket security */
1423 		snprintk(atbuf, sizeof(atbuf), "AT+USOSEC=%d,1,%d", sock->id, sock->id);
1424 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler, NULL, 0U, atbuf,
1425 				     &mdata.sem_response, MDM_CMD_TIMEOUT);
1426 		if (ret < 0) {
1427 			goto error;
1428 		}
1429 		/* Reset the security profile */
1430 		snprintk(atbuf, sizeof(atbuf), "AT+USECPRF=%d", sock->id);
1431 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler, NULL, 0U, atbuf,
1432 				     &mdata.sem_response, MDM_CMD_TIMEOUT);
1433 		if (ret < 0) {
1434 			goto error;
1435 		}
1436 		/* Validate server cert against the CA.  */
1437 		snprintk(atbuf, sizeof(atbuf), "AT+USECPRF=%d,0,1", sock->id);
1438 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler, NULL, 0U, atbuf,
1439 				     &mdata.sem_response, MDM_CMD_TIMEOUT);
1440 		if (ret < 0) {
1441 			goto error;
1442 		}
1443 		/* Use TLSv1.2 only */
1444 		snprintk(atbuf, sizeof(atbuf), "AT+USECPRF=%d,1,3", sock->id);
1445 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler, NULL, 0U, atbuf,
1446 				     &mdata.sem_response, MDM_CMD_TIMEOUT);
1447 		if (ret < 0) {
1448 			goto error;
1449 		}
1450 		/* Set root CA filename */
1451 		snprintk(atbuf, sizeof(atbuf), "AT+USECPRF=%d,3,\"ca\"", sock->id);
1452 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler, NULL, 0U, atbuf,
1453 				     &mdata.sem_response, MDM_CMD_TIMEOUT);
1454 		if (ret < 0) {
1455 			goto error;
1456 		}
1457 	}
1458 
1459 	errno = 0;
1460 	return 0;
1461 
1462 error:
1463 	LOG_ERR("%s ret:%d", buf, ret);
1464 	modem_socket_put(&mdata.socket_config, sock->sock_fd);
1465 	errno = -ret;
1466 	return -1;
1467 }
1468 
1469 /*
1470  * Socket Offload OPS
1471  */
1472 
1473 static const struct socket_op_vtable offload_socket_fd_op_vtable;
1474 
offload_socket(int family,int type,int proto)1475 static int offload_socket(int family, int type, int proto)
1476 {
1477 	int ret;
1478 
1479 	/* defer modem's socket create call to bind() */
1480 	ret = modem_socket_get(&mdata.socket_config, family, type, proto);
1481 	if (ret < 0) {
1482 		errno = -ret;
1483 		return -1;
1484 	}
1485 
1486 	errno = 0;
1487 	return ret;
1488 }
1489 
offload_close(void * obj)1490 static int offload_close(void *obj)
1491 {
1492 	struct modem_socket *sock = (struct modem_socket *)obj;
1493 	char buf[sizeof("AT+USOCL=#\r")];
1494 	int ret;
1495 
1496 	/* make sure socket is allocated and assigned an id */
1497 	if (modem_socket_id_is_assigned(&mdata.socket_config, sock) == false) {
1498 		return 0;
1499 	}
1500 
1501 	if (sock->is_connected || sock->ip_proto == IPPROTO_UDP) {
1502 		snprintk(buf, sizeof(buf), "AT+USOCL=%d", sock->id);
1503 
1504 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1505 				     NULL, 0U, buf,
1506 				     &mdata.sem_response, MDM_CMD_TIMEOUT);
1507 		if (ret < 0) {
1508 			LOG_ERR("%s ret:%d", buf, ret);
1509 		}
1510 	}
1511 
1512 	modem_socket_put(&mdata.socket_config, sock->sock_fd);
1513 	return 0;
1514 }
1515 
offload_bind(void * obj,const struct sockaddr * addr,socklen_t addrlen)1516 static int offload_bind(void *obj, const struct sockaddr *addr,
1517 			socklen_t addrlen)
1518 {
1519 	struct modem_socket *sock = (struct modem_socket *)obj;
1520 
1521 	/* save bind address information */
1522 	memcpy(&sock->src, addr, sizeof(*addr));
1523 
1524 	/* make sure we've created the socket */
1525 	if (modem_socket_is_allocated(&mdata.socket_config, sock) == true) {
1526 		if (create_socket(sock, addr) < 0) {
1527 			return -1;
1528 		}
1529 	}
1530 
1531 	return 0;
1532 }
1533 
offload_connect(void * obj,const struct sockaddr * addr,socklen_t addrlen)1534 static int offload_connect(void *obj, const struct sockaddr *addr,
1535 			   socklen_t addrlen)
1536 {
1537 	struct modem_socket *sock = (struct modem_socket *)obj;
1538 	int ret;
1539 	char buf[sizeof("AT+USOCO=###,!####.####.####.####.####.####.####.####!,#####,#\r")];
1540 	uint16_t dst_port = 0U;
1541 	char ip_str[NET_IPV6_ADDR_LEN];
1542 
1543 	if (!addr) {
1544 		errno = EINVAL;
1545 		return -1;
1546 	}
1547 
1548 	/* make sure socket has been allocated */
1549 	if (modem_socket_is_allocated(&mdata.socket_config, sock) == false) {
1550 		LOG_ERR("Invalid socket_id(%d) from fd:%d",
1551 			sock->id, sock->sock_fd);
1552 		errno = EINVAL;
1553 		return -1;
1554 	}
1555 
1556 	/* make sure we've created the socket */
1557 	if (modem_socket_id_is_assigned(&mdata.socket_config, sock) == false) {
1558 		if (create_socket(sock, NULL) < 0) {
1559 			return -1;
1560 		}
1561 	}
1562 
1563 	memcpy(&sock->dst, addr, sizeof(*addr));
1564 	if (addr->sa_family == AF_INET6) {
1565 		dst_port = ntohs(net_sin6(addr)->sin6_port);
1566 	} else if (addr->sa_family == AF_INET) {
1567 		dst_port = ntohs(net_sin(addr)->sin_port);
1568 	} else {
1569 		errno = EAFNOSUPPORT;
1570 		return -1;
1571 	}
1572 
1573 	/* skip socket connect if UDP */
1574 	if (sock->ip_proto == IPPROTO_UDP) {
1575 		errno = 0;
1576 		return 0;
1577 	}
1578 
1579 	ret = modem_context_sprint_ip_addr(addr, ip_str, sizeof(ip_str));
1580 	if (ret != 0) {
1581 		errno = -ret;
1582 		LOG_ERR("Error formatting IP string %d", ret);
1583 		return -1;
1584 	}
1585 
1586 	snprintk(buf, sizeof(buf), "AT+USOCO=%d,\"%s\",%d", sock->id,
1587 		ip_str, dst_port);
1588 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1589 			     NULL, 0U, buf,
1590 			     &mdata.sem_response, MDM_CMD_CONN_TIMEOUT);
1591 	if (ret < 0) {
1592 		LOG_ERR("%s ret:%d", buf, ret);
1593 		errno = -ret;
1594 		return -1;
1595 	}
1596 
1597 	sock->is_connected = true;
1598 	errno = 0;
1599 	return 0;
1600 }
1601 
offload_recvfrom(void * obj,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)1602 static ssize_t offload_recvfrom(void *obj, void *buf, size_t len,
1603 				int flags, struct sockaddr *from,
1604 				socklen_t *fromlen)
1605 {
1606 	struct modem_socket *sock = (struct modem_socket *)obj;
1607 	int ret, next_packet_size;
1608 	static const struct modem_cmd cmd[] = {
1609 		MODEM_CMD("+USORF: ", on_cmd_sockreadfrom, 4U, ","),
1610 		MODEM_CMD("+USORD: ", on_cmd_sockread, 2U, ","),
1611 	};
1612 	char sendbuf[sizeof("AT+USORF=#,#####\r")];
1613 	struct socket_read_data sock_data;
1614 
1615 	if (!buf || len == 0) {
1616 		errno = EINVAL;
1617 		return -1;
1618 	}
1619 
1620 	if (flags & ZSOCK_MSG_PEEK) {
1621 		errno = ENOTSUP;
1622 		return -1;
1623 	}
1624 
1625 	next_packet_size = modem_socket_next_packet_size(&mdata.socket_config,
1626 							 sock);
1627 	if (!next_packet_size) {
1628 		if (flags & ZSOCK_MSG_DONTWAIT) {
1629 			errno = EAGAIN;
1630 			return -1;
1631 		}
1632 
1633 		if (!sock->is_connected && sock->ip_proto != IPPROTO_UDP) {
1634 			errno = 0;
1635 			return 0;
1636 		}
1637 
1638 		modem_socket_wait_data(&mdata.socket_config, sock);
1639 		next_packet_size = modem_socket_next_packet_size(
1640 			&mdata.socket_config, sock);
1641 	}
1642 
1643 	/*
1644 	 * Binary and ASCII mode allows sending MDM_MAX_DATA_LENGTH bytes to
1645 	 * the socket in one command
1646 	 */
1647 	if (next_packet_size > MDM_MAX_DATA_LENGTH) {
1648 		next_packet_size = MDM_MAX_DATA_LENGTH;
1649 	}
1650 
1651 	snprintk(sendbuf, sizeof(sendbuf), "AT+USO%s=%d,%zd",
1652 		 sock->ip_proto == IPPROTO_UDP ? "RF" : "RD", sock->id,
1653 		 len < next_packet_size ? len : next_packet_size);
1654 
1655 	/* socket read settings */
1656 	(void)memset(&sock_data, 0, sizeof(sock_data));
1657 	sock_data.recv_buf = buf;
1658 	sock_data.recv_buf_len = len;
1659 	sock_data.recv_addr = from;
1660 	sock->data = &sock_data;
1661 
1662 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
1663 			     cmd, ARRAY_SIZE(cmd), sendbuf, &mdata.sem_response,
1664 			     MDM_CMD_TIMEOUT);
1665 	if (ret < 0) {
1666 		errno = -ret;
1667 		ret = -1;
1668 		goto exit;
1669 	}
1670 
1671 	/* HACK: use dst address as from */
1672 	if (from && fromlen) {
1673 		*fromlen = sizeof(sock->dst);
1674 		memcpy(from, &sock->dst, *fromlen);
1675 	}
1676 
1677 	/* return length of received data */
1678 	errno = 0;
1679 	ret = sock_data.recv_read_len;
1680 
1681 exit:
1682 	/* clear socket data */
1683 	sock->data = NULL;
1684 	return ret;
1685 }
1686 
offload_sendto(void * obj,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)1687 static ssize_t offload_sendto(void *obj, const void *buf, size_t len,
1688 			      int flags, const struct sockaddr *to,
1689 			      socklen_t tolen)
1690 {
1691 	struct iovec msg_iov = {
1692 		.iov_base = (void *)buf,
1693 		.iov_len = len,
1694 	};
1695 	struct msghdr msg = {
1696 		.msg_iovlen = 1,
1697 		.msg_name = (struct sockaddr *)to,
1698 		.msg_namelen = tolen,
1699 		.msg_iov = &msg_iov,
1700 	};
1701 
1702 	int ret = send_socket_data(obj, &msg, MDM_CMD_TIMEOUT);
1703 	if (ret < 0) {
1704 		errno = -ret;
1705 		return -1;
1706 	}
1707 
1708 	errno = 0;
1709 	return ret;
1710 }
1711 
offload_ioctl(void * obj,unsigned int request,va_list args)1712 static int offload_ioctl(void *obj, unsigned int request, va_list args)
1713 {
1714 	switch (request) {
1715 	case ZFD_IOCTL_POLL_PREPARE: {
1716 		struct zsock_pollfd *pfd;
1717 		struct k_poll_event **pev;
1718 		struct k_poll_event *pev_end;
1719 
1720 		pfd = va_arg(args, struct zsock_pollfd *);
1721 		pev = va_arg(args, struct k_poll_event **);
1722 		pev_end = va_arg(args, struct k_poll_event *);
1723 
1724 		return modem_socket_poll_prepare(&mdata.socket_config, obj, pfd, pev, pev_end);
1725 	}
1726 	case ZFD_IOCTL_POLL_UPDATE: {
1727 		struct zsock_pollfd *pfd;
1728 		struct k_poll_event **pev;
1729 
1730 		pfd = va_arg(args, struct zsock_pollfd *);
1731 		pev = va_arg(args, struct k_poll_event **);
1732 
1733 		return modem_socket_poll_update(obj, pfd, pev);
1734 	}
1735 
1736 	case F_GETFL:
1737 		return 0;
1738 
1739 	default:
1740 		errno = EINVAL;
1741 		return -1;
1742 	}
1743 }
1744 
offload_read(void * obj,void * buffer,size_t count)1745 static ssize_t offload_read(void *obj, void *buffer, size_t count)
1746 {
1747 	return offload_recvfrom(obj, buffer, count, 0, NULL, 0);
1748 }
1749 
offload_write(void * obj,const void * buffer,size_t count)1750 static ssize_t offload_write(void *obj, const void *buffer, size_t count)
1751 {
1752 	return offload_sendto(obj, buffer, count, 0, NULL, 0);
1753 }
1754 
offload_sendmsg(void * obj,const struct msghdr * msg,int flags)1755 static ssize_t offload_sendmsg(void *obj, const struct msghdr *msg, int flags)
1756 {
1757 	ssize_t sent = 0;
1758 	int bkp_iovec_idx;
1759 	struct iovec bkp_iovec = {0};
1760 	struct msghdr crafted_msg = {
1761 		.msg_name = msg->msg_name,
1762 		.msg_namelen = msg->msg_namelen,
1763 	};
1764 	size_t full_len = 0;
1765 	int ret;
1766 
1767 	/* Compute the full length to be send and check for invalid values */
1768 	for (int i = 0; i < msg->msg_iovlen; i++) {
1769 		if (!msg->msg_iov[i].iov_base || msg->msg_iov[i].iov_len == 0) {
1770 			errno = EINVAL;
1771 			return -1;
1772 		}
1773 		full_len += msg->msg_iov[i].iov_len;
1774 	}
1775 
1776 	LOG_DBG("msg_iovlen:%zd flags:%d, full_len:%zd",
1777 		msg->msg_iovlen, flags, full_len);
1778 
1779 	while (full_len > sent) {
1780 		int removed = 0;
1781 		int i = 0;
1782 
1783 		crafted_msg.msg_iovlen = msg->msg_iovlen;
1784 		crafted_msg.msg_iov = &msg->msg_iov[0];
1785 
1786 		bkp_iovec_idx = -1;
1787 		/*  Iterate on iovec to remove the bytes already sent */
1788 		while (removed < sent) {
1789 			int to_removed = sent - removed;
1790 
1791 			if (to_removed >= msg->msg_iov[i].iov_len) {
1792 				crafted_msg.msg_iovlen -= 1;
1793 				crafted_msg.msg_iov = &msg->msg_iov[i + 1];
1794 
1795 				removed += msg->msg_iov[i].iov_len;
1796 			} else {
1797 				/* Backup msg->msg_iov[i] before "removing"
1798 				 * starting bytes already send.
1799 				 */
1800 				bkp_iovec_idx = i;
1801 				bkp_iovec.iov_len = msg->msg_iov[i].iov_len;
1802 				bkp_iovec.iov_base = msg->msg_iov[i].iov_base;
1803 
1804 				/* Update msg->msg_iov[i] to "remove"
1805 				 * starting bytes already send.
1806 				 */
1807 				msg->msg_iov[i].iov_len -= to_removed;
1808 				msg->msg_iov[i].iov_base = &(((uint8_t *)msg->msg_iov[i].iov_base)[to_removed]);
1809 
1810 				removed += to_removed;
1811 			}
1812 
1813 			i++;
1814 		}
1815 
1816 		ret = send_socket_data(obj, &crafted_msg, MDM_CMD_TIMEOUT);
1817 
1818 		/* Restore backup iovec when necessary */
1819 		if (bkp_iovec_idx != -1) {
1820 			msg->msg_iov[bkp_iovec_idx].iov_len = bkp_iovec.iov_len;
1821 			msg->msg_iov[bkp_iovec_idx].iov_base = bkp_iovec.iov_base;
1822 		}
1823 
1824 		/* Handle send_socket_data() returned value */
1825 		if (ret < 0) {
1826 			errno = -ret;
1827 			return -1;
1828 		}
1829 
1830 		sent += ret;
1831 	}
1832 
1833 	return (ssize_t)sent;
1834 }
1835 
1836 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
map_credentials(struct modem_socket * sock,const void * optval,socklen_t optlen)1837 static int map_credentials(struct modem_socket *sock, const void *optval, socklen_t optlen)
1838 {
1839 	sec_tag_t *sec_tags = (sec_tag_t *)optval;
1840 	int ret = 0;
1841 	int tags_len;
1842 	sec_tag_t tag;
1843 	int id;
1844 	int i;
1845 	struct tls_credential *cert;
1846 
1847 	if ((optlen % sizeof(sec_tag_t)) != 0 || (optlen == 0)) {
1848 		return -EINVAL;
1849 	}
1850 
1851 	tags_len = optlen / sizeof(sec_tag_t);
1852 	/* For each tag, retrieve the credentials value and type: */
1853 	for (i = 0; i < tags_len; i++) {
1854 		tag = sec_tags[i];
1855 		cert = credential_next_get(tag, NULL);
1856 		while (cert != NULL) {
1857 			switch (cert->type) {
1858 			case TLS_CREDENTIAL_CA_CERTIFICATE:
1859 				id = 0;
1860 				break;
1861 			case TLS_CREDENTIAL_NONE:
1862 			case TLS_CREDENTIAL_PSK:
1863 			case TLS_CREDENTIAL_PSK_ID:
1864 			default:
1865 				/* Not handled */
1866 				return -EINVAL;
1867 			}
1868 			struct modem_cmd cmd[] = {
1869 				MODEM_CMD("+USECMNG: ", on_cmd_cert_write, 3U, ","),
1870 			};
1871 			ret = send_cert(sock, cmd, 1, cert->buf, cert->len, id);
1872 			if (ret < 0) {
1873 				return ret;
1874 			}
1875 
1876 			cert = credential_next_get(tag, cert);
1877 		}
1878 	}
1879 
1880 	return 0;
1881 }
1882 #else
map_credentials(struct modem_socket * sock,const void * optval,socklen_t optlen)1883 static int map_credentials(struct modem_socket *sock, const void *optval, socklen_t optlen)
1884 {
1885 	return -EINVAL;
1886 }
1887 #endif
1888 
offload_setsockopt(void * obj,int level,int optname,const void * optval,socklen_t optlen)1889 static int offload_setsockopt(void *obj, int level, int optname,
1890 			      const void *optval, socklen_t optlen)
1891 {
1892 	struct modem_socket *sock = (struct modem_socket *)obj;
1893 
1894 	int ret;
1895 
1896 	if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS) && level == SOL_TLS) {
1897 		switch (optname) {
1898 		case TLS_SEC_TAG_LIST:
1899 			ret = map_credentials(sock, optval, optlen);
1900 			break;
1901 		case TLS_HOSTNAME:
1902 			LOG_WRN("TLS_HOSTNAME option is not supported");
1903 			return -EINVAL;
1904 		case TLS_PEER_VERIFY:
1905 			if (*(uint32_t *)optval != TLS_PEER_VERIFY_REQUIRED) {
1906 				LOG_WRN("Disabling peer verification is not supported");
1907 				return -EINVAL;
1908 			}
1909 			ret = 0;
1910 			break;
1911 		default:
1912 			return -EINVAL;
1913 		}
1914 	} else {
1915 		return -EINVAL;
1916 	}
1917 
1918 	return ret;
1919 }
1920 
1921 
1922 static const struct socket_op_vtable offload_socket_fd_op_vtable = {
1923 	.fd_vtable = {
1924 		.read = offload_read,
1925 		.write = offload_write,
1926 		.close = offload_close,
1927 		.ioctl = offload_ioctl,
1928 	},
1929 	.bind = offload_bind,
1930 	.connect = offload_connect,
1931 	.sendto = offload_sendto,
1932 	.recvfrom = offload_recvfrom,
1933 	.listen = NULL,
1934 	.accept = NULL,
1935 	.sendmsg = offload_sendmsg,
1936 	.getsockopt = NULL,
1937 	.setsockopt = offload_setsockopt,
1938 };
1939 
offload_is_supported(int family,int type,int proto)1940 static bool offload_is_supported(int family, int type, int proto)
1941 {
1942 	if (family != AF_INET &&
1943 	    family != AF_INET6) {
1944 		return false;
1945 	}
1946 
1947 	if (type != SOCK_DGRAM &&
1948 	    type != SOCK_STREAM) {
1949 		return false;
1950 	}
1951 
1952 	if (proto != IPPROTO_TCP &&
1953 	    proto != IPPROTO_UDP &&
1954 	    proto != IPPROTO_TLS_1_2) {
1955 		return false;
1956 	}
1957 
1958 	return true;
1959 }
1960 
1961 NET_SOCKET_OFFLOAD_REGISTER(ublox_sara_r4, CONFIG_NET_SOCKETS_OFFLOAD_PRIORITY,
1962 			    AF_UNSPEC, offload_is_supported, offload_socket);
1963 
1964 #if defined(CONFIG_DNS_RESOLVER)
1965 /* TODO: This is a bare-bones implementation of DNS handling
1966  * We ignore most of the hints like ai_family, ai_protocol and ai_socktype.
1967  * Later, we can add additional handling if it makes sense.
1968  */
offload_getaddrinfo(const char * node,const char * service,const struct zsock_addrinfo * hints,struct zsock_addrinfo ** res)1969 static int offload_getaddrinfo(const char *node, const char *service,
1970 			       const struct zsock_addrinfo *hints,
1971 			       struct zsock_addrinfo **res)
1972 {
1973 	static const struct modem_cmd cmd =
1974 		MODEM_CMD("+UDNSRN: ", on_cmd_dns, 1U, ",");
1975 	uint32_t port = 0U;
1976 	int ret;
1977 	/* DNS command + 128 bytes for domain name parameter */
1978 	char sendbuf[sizeof("AT+UDNSRN=#,'[]'\r") + 128];
1979 
1980 	/* init result */
1981 	(void)memset(&result, 0, sizeof(result));
1982 	(void)memset(&result_addr, 0, sizeof(result_addr));
1983 	/* FIXME: Hard-code DNS to return only IPv4 */
1984 	result.ai_family = AF_INET;
1985 	result_addr.sa_family = AF_INET;
1986 	result.ai_addr = &result_addr;
1987 	result.ai_addrlen = sizeof(result_addr);
1988 	result.ai_canonname = result_canonname;
1989 	result_canonname[0] = '\0';
1990 
1991 	if (service) {
1992 		port = ATOI(service, 0U, "port");
1993 		if (port < 1 || port > USHRT_MAX) {
1994 			return DNS_EAI_SERVICE;
1995 		}
1996 	}
1997 
1998 	if (port > 0U) {
1999 		/* FIXME: DNS is hard-coded to return only IPv4 */
2000 		if (result.ai_family == AF_INET) {
2001 			net_sin(&result_addr)->sin_port = htons(port);
2002 		}
2003 	}
2004 
2005 	/* check to see if node is an IP address */
2006 	if (net_addr_pton(result.ai_family, node,
2007 			  &((struct sockaddr_in *)&result_addr)->sin_addr)
2008 	    == 0) {
2009 		*res = &result;
2010 		return 0;
2011 	}
2012 
2013 	/* user flagged node as numeric host, but we failed net_addr_pton */
2014 	if (hints && hints->ai_flags & AI_NUMERICHOST) {
2015 		return DNS_EAI_NONAME;
2016 	}
2017 
2018 	snprintk(sendbuf, sizeof(sendbuf), "AT+UDNSRN=0,\"%s\"", node);
2019 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
2020 			     &cmd, 1U, sendbuf, &mdata.sem_response,
2021 			     MDM_DNS_TIMEOUT);
2022 	if (ret < 0) {
2023 		return ret;
2024 	}
2025 
2026 	LOG_DBG("DNS RESULT: %s",
2027 		net_addr_ntop(result.ai_family,
2028 					 &net_sin(&result_addr)->sin_addr,
2029 					 sendbuf, NET_IPV4_ADDR_LEN));
2030 
2031 	*res = (struct zsock_addrinfo *)&result;
2032 	return 0;
2033 }
2034 
offload_freeaddrinfo(struct zsock_addrinfo * res)2035 static void offload_freeaddrinfo(struct zsock_addrinfo *res)
2036 {
2037 	/* using static result from offload_getaddrinfo() -- no need to free */
2038 	ARG_UNUSED(res);
2039 }
2040 
2041 static const struct socket_dns_offload offload_dns_ops = {
2042 	.getaddrinfo = offload_getaddrinfo,
2043 	.freeaddrinfo = offload_freeaddrinfo,
2044 };
2045 #endif
2046 
net_offload_dummy_get(sa_family_t family,enum net_sock_type type,enum net_ip_protocol ip_proto,struct net_context ** context)2047 static int net_offload_dummy_get(sa_family_t family,
2048 				 enum net_sock_type type,
2049 				 enum net_ip_protocol ip_proto,
2050 				 struct net_context **context)
2051 {
2052 
2053 	LOG_ERR("CONFIG_NET_SOCKETS_OFFLOAD must be enabled for this driver");
2054 
2055 	return -ENOTSUP;
2056 }
2057 
2058 /* placeholders, until Zephyr IP stack updated to handle a NULL net_offload */
2059 static struct net_offload modem_net_offload = {
2060 	.get = net_offload_dummy_get,
2061 };
2062 
2063 #define HASH_MULTIPLIER		37
hash32(char * str,int len)2064 static uint32_t hash32(char *str, int len)
2065 {
2066 	uint32_t h = 0;
2067 	int i;
2068 
2069 	for (i = 0; i < len; ++i) {
2070 		h = (h * HASH_MULTIPLIER) + str[i];
2071 	}
2072 
2073 	return h;
2074 }
2075 
modem_get_mac(const struct device * dev)2076 static inline uint8_t *modem_get_mac(const struct device *dev)
2077 {
2078 	struct modem_data *data = dev->data;
2079 	uint32_t hash_value;
2080 
2081 	data->mac_addr[0] = 0x00;
2082 	data->mac_addr[1] = 0x10;
2083 
2084 	/* use IMEI for mac_addr */
2085 	hash_value = hash32(mdata.mdm_imei, strlen(mdata.mdm_imei));
2086 
2087 	UNALIGNED_PUT(hash_value, (uint32_t *)(data->mac_addr + 2));
2088 
2089 	return data->mac_addr;
2090 }
2091 
2092 static int offload_socket(int family, int type, int proto);
2093 
modem_net_iface_init(struct net_if * iface)2094 static void modem_net_iface_init(struct net_if *iface)
2095 {
2096 	const struct device *dev = net_if_get_device(iface);
2097 	struct modem_data *data = dev->data;
2098 
2099 	/* Direct socket offload used instead of net offload: */
2100 	iface->if_dev->offload = &modem_net_offload;
2101 	net_if_set_link_addr(iface, modem_get_mac(dev),
2102 			     sizeof(data->mac_addr),
2103 			     NET_LINK_ETHERNET);
2104 	data->net_iface = iface;
2105 #ifdef CONFIG_DNS_RESOLVER
2106 	socket_offload_dns_register(&offload_dns_ops);
2107 #endif
2108 
2109 	net_if_socket_offload_set(iface, offload_socket);
2110 }
2111 
2112 static struct offloaded_if_api api_funcs = {
2113 	.iface_api.init = modem_net_iface_init,
2114 };
2115 
2116 static const struct modem_cmd response_cmds[] = {
2117 	MODEM_CMD("OK", on_cmd_ok, 0U, ""), /* 3GPP */
2118 	MODEM_CMD("ERROR", on_cmd_error, 0U, ""), /* 3GPP */
2119 	MODEM_CMD("+CME ERROR: ", on_cmd_exterror, 1U, ""),
2120 	MODEM_CMD_DIRECT("@", on_prompt),
2121 };
2122 
2123 static const struct modem_cmd unsol_cmds[] = {
2124 	MODEM_CMD("+UUSOCL: ", on_cmd_socknotifyclose, 1U, ""),
2125 	MODEM_CMD("+UUSORD: ", on_cmd_socknotifydata, 2U, ","),
2126 	MODEM_CMD("+UUSORF: ", on_cmd_socknotifydata, 2U, ","),
2127 	MODEM_CMD("+CREG: ", on_cmd_socknotifycreg, 1U, ""),
2128 };
2129 
modem_init(const struct device * dev)2130 static int modem_init(const struct device *dev)
2131 {
2132 	int ret = 0;
2133 
2134 	ARG_UNUSED(dev);
2135 
2136 	k_sem_init(&mdata.sem_response, 0, 1);
2137 	k_sem_init(&mdata.sem_prompt, 0, 1);
2138 
2139 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
2140 	/* initialize the work queue */
2141 	k_work_queue_start(&modem_workq, modem_workq_stack,
2142 			   K_KERNEL_STACK_SIZEOF(modem_workq_stack),
2143 			   K_PRIO_COOP(7), NULL);
2144 #endif
2145 
2146 	/* socket config */
2147 	ret = modem_socket_init(&mdata.socket_config, &mdata.sockets[0], ARRAY_SIZE(mdata.sockets),
2148 				MDM_BASE_SOCKET_NUM, false, &offload_socket_fd_op_vtable);
2149 	if (ret < 0) {
2150 		goto error;
2151 	}
2152 
2153 	/* cmd handler */
2154 	const struct modem_cmd_handler_config cmd_handler_config = {
2155 		.match_buf = &mdata.cmd_match_buf[0],
2156 		.match_buf_len = sizeof(mdata.cmd_match_buf),
2157 		.buf_pool = &mdm_recv_pool,
2158 		.alloc_timeout = K_NO_WAIT,
2159 		.eol = "\r",
2160 		.user_data = NULL,
2161 		.response_cmds = response_cmds,
2162 		.response_cmds_len = ARRAY_SIZE(response_cmds),
2163 		.unsol_cmds = unsol_cmds,
2164 		.unsol_cmds_len = ARRAY_SIZE(unsol_cmds),
2165 	};
2166 
2167 	ret = modem_cmd_handler_init(&mctx.cmd_handler, &mdata.cmd_handler_data,
2168 				     &cmd_handler_config);
2169 	if (ret < 0) {
2170 		goto error;
2171 	}
2172 
2173 	/* modem interface */
2174 	const struct modem_iface_uart_config uart_config = {
2175 		.rx_rb_buf = &mdata.iface_rb_buf[0],
2176 		.rx_rb_buf_len = sizeof(mdata.iface_rb_buf),
2177 		.dev = MDM_UART_DEV,
2178 		.hw_flow_control = DT_PROP(MDM_UART_NODE, hw_flow_control),
2179 	};
2180 
2181 	ret = modem_iface_uart_init(&mctx.iface, &mdata.iface_data, &uart_config);
2182 	if (ret < 0) {
2183 		goto error;
2184 	}
2185 
2186 	/* modem data storage */
2187 	mctx.data_manufacturer = mdata.mdm_manufacturer;
2188 	mctx.data_model = mdata.mdm_model;
2189 	mctx.data_revision = mdata.mdm_revision;
2190 	mctx.data_imei = mdata.mdm_imei;
2191 	mctx.data_rssi = &mdata.mdm_rssi;
2192 
2193 	/* pin setup */
2194 	ret = gpio_pin_configure_dt(&power_gpio, GPIO_OUTPUT);
2195 	if (ret < 0) {
2196 		LOG_ERR("Failed to configure %s pin", "power");
2197 		goto error;
2198 	}
2199 
2200 #if DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
2201 	ret = gpio_pin_configure_dt(&reset_gpio, GPIO_OUTPUT);
2202 	if (ret < 0) {
2203 		LOG_ERR("Failed to configure %s pin", "reset");
2204 		goto error;
2205 	}
2206 #endif
2207 
2208 #if DT_INST_NODE_HAS_PROP(0, mdm_vint_gpios)
2209 	ret = gpio_pin_configure_dt(&vint_gpio, GPIO_INPUT);
2210 	if (ret < 0) {
2211 		LOG_ERR("Failed to configure %s pin", "vint");
2212 		goto error;
2213 	}
2214 #endif
2215 
2216 	mctx.driver_data = &mdata;
2217 
2218 	ret = modem_context_register(&mctx);
2219 	if (ret < 0) {
2220 		LOG_ERR("Error registering modem context: %d", ret);
2221 		goto error;
2222 	}
2223 
2224 	/* start RX thread */
2225 	k_thread_create(&modem_rx_thread, modem_rx_stack,
2226 			K_KERNEL_STACK_SIZEOF(modem_rx_stack),
2227 			modem_rx,
2228 			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
2229 
2230 #if defined(CONFIG_MODEM_UBLOX_SARA_RSSI_WORK)
2231 	/* init RSSI query */
2232 	k_work_init_delayable(&mdata.rssi_query_work, modem_rssi_query_work);
2233 #endif
2234 
2235 	modem_reset();
2236 
2237 error:
2238 	return ret;
2239 }
2240 
2241 NET_DEVICE_DT_INST_OFFLOAD_DEFINE(0, modem_init, NULL,
2242 				  &mdata, NULL,
2243 				  CONFIG_MODEM_UBLOX_SARA_R4_INIT_PRIORITY,
2244 				  &api_funcs,
2245 				  MDM_MAX_DATA_LENGTH);
2246