1 /*
2  * Copyright (c) 2018 Foundries.io
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT wnc_m14a2a
8 
9 #define LOG_DOMAIN modem_wncm14a2a
10 #define LOG_LEVEL CONFIG_MODEM_LOG_LEVEL
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(LOG_DOMAIN);
13 
14 #include <zephyr/types.h>
15 #include <stddef.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include <zephyr/kernel.h>
20 #include <zephyr/drivers/gpio.h>
21 #include <zephyr/device.h>
22 #include <zephyr/init.h>
23 #include <zephyr/random/random.h>
24 
25 #include <zephyr/net/net_context.h>
26 #include <zephyr/net/net_if.h>
27 #include <zephyr/net/net_offload.h>
28 #include <zephyr/net/offloaded_netdev.h>
29 #include <zephyr/net/net_pkt.h>
30 #if defined(CONFIG_NET_IPV6)
31 #include "ipv6.h"
32 #endif
33 #if defined(CONFIG_NET_IPV4)
34 #include "ipv4.h"
35 #endif
36 #if defined(CONFIG_NET_UDP)
37 #include "udp_internal.h"
38 #endif
39 
40 #include "modem_receiver.h"
41 
42 /* Uncomment the #define below to enable a hexdump of all incoming
43  * data from the modem receiver
44  */
45 /* #define ENABLE_VERBOSE_MODEM_RECV_HEXDUMP	1 */
46 
47 /* pin settings */
48 enum mdm_control_pins {
49 	MDM_BOOT_MODE_SEL = 0,
50 	MDM_POWER,
51 	MDM_KEEP_AWAKE,
52 	MDM_RESET,
53 	SHLD_3V3_1V8_SIG_TRANS_ENA,
54 #if DT_INST_NODE_HAS_PROP(0, mdm_send_ok_gpios)
55 	MDM_SEND_OK,
56 #endif
57 	MAX_MDM_CONTROL_PINS,
58 };
59 
60 #define MDM_UART_DEV			DEVICE_DT_GET(DT_INST_BUS(0))
61 
62 #define MDM_BOOT_MODE_SPECIAL		0
63 #define MDM_BOOT_MODE_NORMAL		1
64 
65 #define MDM_CMD_TIMEOUT			(5 * MSEC_PER_SEC)
66 #define MDM_CMD_SEND_TIMEOUT		(10 * MSEC_PER_SEC)
67 #define MDM_CMD_CONN_TIMEOUT		(31 * MSEC_PER_SEC)
68 
69 #define MDM_MAX_DATA_LENGTH		1500
70 
71 #define MDM_RECV_MAX_BUF		30
72 #define MDM_RECV_BUF_SIZE		128
73 
74 #define MDM_MAX_SOCKETS			6
75 
76 #define BUF_ALLOC_TIMEOUT K_SECONDS(1)
77 
78 #define CMD_HANDLER(cmd_, cb_) { \
79 	.cmd = cmd_, \
80 	.cmd_len = (uint16_t)sizeof(cmd_)-1, \
81 	.func = on_cmd_ ## cb_ \
82 }
83 
84 #define MDM_MANUFACTURER_LENGTH		10
85 #define MDM_MODEL_LENGTH		16
86 #define MDM_REVISION_LENGTH		64
87 #define MDM_IMEI_LENGTH			16
88 
89 #define RSSI_TIMEOUT_SECS		30
90 
91 NET_BUF_POOL_DEFINE(mdm_recv_pool, MDM_RECV_MAX_BUF, MDM_RECV_BUF_SIZE,
92 		    0, NULL);
93 
94 static uint8_t mdm_recv_buf[MDM_MAX_DATA_LENGTH];
95 
96 /* RX thread structures */
97 K_KERNEL_STACK_DEFINE(wncm14a2a_rx_stack,
98 		       CONFIG_MODEM_WNCM14A2A_RX_STACK_SIZE);
99 struct k_thread wncm14a2a_rx_thread;
100 
101 /* RX thread work queue */
102 K_KERNEL_STACK_DEFINE(wncm14a2a_workq_stack,
103 		      CONFIG_MODEM_WNCM14A2A_RX_WORKQ_STACK_SIZE);
104 static struct k_work_q wncm14a2a_workq;
105 
106 struct wncm14a2a_socket {
107 	struct net_context *context;
108 	sa_family_t family;
109 	enum net_sock_type type;
110 	enum net_ip_protocol ip_proto;
111 	struct sockaddr src;
112 	struct sockaddr dst;
113 
114 	int socket_id;
115 
116 	/** semaphore */
117 	struct k_sem sock_send_sem;
118 
119 	/** socket callbacks */
120 	struct k_work recv_cb_work;
121 	net_context_recv_cb_t recv_cb;
122 	struct net_pkt *recv_pkt;
123 	void *recv_user_data;
124 };
125 
126 struct wncm14a2a_config {
127 	struct gpio_dt_spec gpio[MAX_MDM_CONTROL_PINS];
128 };
129 
130 struct wncm14a2a_iface_ctx {
131 	struct net_if *iface;
132 	uint8_t mac_addr[6];
133 
134 	/* RX specific attributes */
135 	struct mdm_receiver_context mdm_ctx;
136 
137 	/* socket data */
138 	struct wncm14a2a_socket sockets[MDM_MAX_SOCKETS];
139 	int last_socket_id;
140 	int last_error;
141 
142 	/* semaphores */
143 	struct k_sem response_sem;
144 
145 	/* RSSI work */
146 	struct k_work_delayable rssi_query_work;
147 
148 	/* modem data */
149 	char mdm_manufacturer[MDM_MANUFACTURER_LENGTH];
150 	char mdm_model[MDM_MODEL_LENGTH];
151 	char mdm_revision[MDM_REVISION_LENGTH];
152 	char mdm_imei[MDM_IMEI_LENGTH];
153 	int mdm_rssi;
154 
155 	/* modem state */
156 	int ev_csps;
157 	int ev_rrcstate;
158 };
159 
160 struct cmd_handler {
161 	const char *cmd;
162 	uint16_t cmd_len;
163 	void (*func)(struct net_buf **buf, uint16_t len);
164 };
165 
166 const static struct wncm14a2a_config wncm14a2a_cfg = {
167 	.gpio = {
168 		GPIO_DT_SPEC_INST_GET(0, mdm_boot_mode_sel_gpios),
169 		GPIO_DT_SPEC_INST_GET(0, mdm_power_gpios),
170 		GPIO_DT_SPEC_INST_GET(0, mdm_keep_awake_gpios),
171 		GPIO_DT_SPEC_INST_GET(0, mdm_reset_gpios),
172 		GPIO_DT_SPEC_INST_GET(0, mdm_shld_trans_ena_gpios),
173 #if DT_INST_NODE_HAS_PROP(0, mdm_send_ok_gpios)
174 		GPIO_DT_SPEC_INST_GET(0, mdm_send_ok_gpios),
175 #endif
176 	},
177 };
178 
179 static struct wncm14a2a_iface_ctx ictx;
180 
181 static void wncm14a2a_read_rx(struct net_buf **buf);
182 
183 /*** Verbose Debugging Functions ***/
184 #if defined(ENABLE_VERBOSE_MODEM_RECV_HEXDUMP)
hexdump(const uint8_t * packet,size_t length)185 static inline void hexdump(const uint8_t *packet, size_t length)
186 {
187 	char output[sizeof("xxxxyyyy xxxxyyyy")];
188 	int n = 0, k = 0;
189 	uint8_t byte;
190 
191 	while (length--) {
192 		if (n % 16 == 0) {
193 			printk(" %08X ", n);
194 		}
195 
196 		byte = *packet++;
197 
198 		printk("%02X ", byte);
199 
200 		if (byte < 0x20 || byte > 0x7f) {
201 			output[k++] = '.';
202 		} else {
203 			output[k++] = byte;
204 		}
205 
206 		n++;
207 		if (n % 8 == 0) {
208 			if (n % 16 == 0) {
209 				output[k] = '\0';
210 				printk(" [%s]\n", output);
211 				k = 0;
212 			} else {
213 				printk(" ");
214 			}
215 		}
216 	}
217 
218 	if (n % 16) {
219 		int i;
220 
221 		output[k] = '\0';
222 
223 		for (i = 0; i < (16 - (n % 16)); i++) {
224 			printk("   ");
225 		}
226 
227 		if ((n % 16) < 8) {
228 			printk(" "); /* one extra delimiter after 8 chars */
229 		}
230 
231 		printk(" [%s]\n", output);
232 	}
233 }
234 #else
235 #define hexdump(...)
236 #endif
237 
socket_get(void)238 static struct wncm14a2a_socket *socket_get(void)
239 {
240 	int i;
241 	struct wncm14a2a_socket *sock = NULL;
242 
243 	for (i = 0; i < MDM_MAX_SOCKETS; i++) {
244 		if (!ictx.sockets[i].context) {
245 			sock = &ictx.sockets[i];
246 			break;
247 		}
248 	}
249 
250 	return sock;
251 }
252 
socket_from_id(int socket_id)253 static struct wncm14a2a_socket *socket_from_id(int socket_id)
254 {
255 	int i;
256 	struct wncm14a2a_socket *sock = NULL;
257 
258 	if (socket_id < 1) {
259 		return NULL;
260 	}
261 
262 	for (i = 0; i < MDM_MAX_SOCKETS; i++) {
263 		if (ictx.sockets[i].socket_id == socket_id) {
264 			sock = &ictx.sockets[i];
265 			break;
266 		}
267 	}
268 
269 	return sock;
270 }
271 
socket_put(struct wncm14a2a_socket * sock)272 static void socket_put(struct wncm14a2a_socket *sock)
273 {
274 	if (!sock) {
275 		return;
276 	}
277 
278 	sock->context = NULL;
279 	sock->socket_id = 0;
280 	(void)memset(&sock->src, 0, sizeof(struct sockaddr));
281 	(void)memset(&sock->dst, 0, sizeof(struct sockaddr));
282 }
283 
wncm14a2a_sprint_ip_addr(const struct sockaddr * addr)284 char *wncm14a2a_sprint_ip_addr(const struct sockaddr *addr)
285 {
286 	static char buf[NET_IPV6_ADDR_LEN];
287 
288 #if defined(CONFIG_NET_IPV6)
289 	if (addr->sa_family == AF_INET6) {
290 		return net_addr_ntop(AF_INET6, &net_sin6(addr)->sin6_addr,
291 				     buf, sizeof(buf));
292 	} else
293 #endif
294 #if defined(CONFIG_NET_IPV4)
295 	if (addr->sa_family == AF_INET) {
296 		return net_addr_ntop(AF_INET, &net_sin(addr)->sin_addr,
297 				     buf, sizeof(buf));
298 	} else
299 #endif
300 	{
301 		LOG_ERR("Unknown IP address family:%d", addr->sa_family);
302 		return NULL;
303 	}
304 }
305 
306 /* Send an AT command with a series of response handlers */
send_at_cmd(struct wncm14a2a_socket * sock,const uint8_t * data,int timeout)307 static int send_at_cmd(struct wncm14a2a_socket *sock,
308 			const uint8_t *data, int timeout)
309 {
310 	int ret;
311 
312 	ictx.last_error = 0;
313 
314 	LOG_DBG("OUT: [%s]", data);
315 	mdm_receiver_send(&ictx.mdm_ctx, data, strlen(data));
316 	mdm_receiver_send(&ictx.mdm_ctx, "\r\n", 2);
317 
318 	if (timeout == 0) {
319 		return 0;
320 	}
321 
322 	if (!sock) {
323 		k_sem_reset(&ictx.response_sem);
324 		ret = k_sem_take(&ictx.response_sem, K_MSEC(timeout));
325 	} else {
326 		k_sem_reset(&sock->sock_send_sem);
327 		ret = k_sem_take(&sock->sock_send_sem, K_MSEC(timeout));
328 	}
329 
330 	if (ret == 0) {
331 		ret = ictx.last_error;
332 	} else if (ret == -EAGAIN) {
333 		ret = -ETIMEDOUT;
334 	}
335 
336 	return ret;
337 }
338 
send_data(struct wncm14a2a_socket * sock,struct net_pkt * pkt)339 static int send_data(struct wncm14a2a_socket *sock, struct net_pkt *pkt)
340 {
341 	int ret;
342 	struct net_buf *frag;
343 	char buf[sizeof("AT@SOCKWRITE=#,####,1\r")];
344 
345 	if (!sock) {
346 		return -EINVAL;
347 	}
348 
349 	ictx.last_error = 0;
350 
351 	frag = pkt->frags;
352 	/* use SOCKWRITE with binary mode formatting */
353 	snprintk(buf, sizeof(buf), "AT@SOCKWRITE=%d,%zu,1\r",
354 		 sock->socket_id, net_buf_frags_len(frag));
355 	mdm_receiver_send(&ictx.mdm_ctx, buf, strlen(buf));
356 
357 	/* Loop through packet data and send */
358 	while (frag) {
359 		mdm_receiver_send(&ictx.mdm_ctx,
360 				  frag->data, frag->len);
361 		frag = frag->frags;
362 	}
363 
364 	mdm_receiver_send(&ictx.mdm_ctx, "\r\n", 2);
365 	k_sem_reset(&sock->sock_send_sem);
366 	ret = k_sem_take(&sock->sock_send_sem, K_MSEC(MDM_CMD_SEND_TIMEOUT));
367 	if (ret == 0) {
368 		ret = ictx.last_error;
369 	} else if (ret == -EAGAIN) {
370 		ret = -ETIMEDOUT;
371 	}
372 
373 	return ret;
374 }
375 
376 /*** NET_BUF HELPERS ***/
377 
is_crlf(uint8_t c)378 static bool is_crlf(uint8_t c)
379 {
380 	if (c == '\n' || c == '\r') {
381 		return true;
382 	} else {
383 		return false;
384 	}
385 }
386 
net_buf_skipcrlf(struct net_buf ** buf)387 static void net_buf_skipcrlf(struct net_buf **buf)
388 {
389 	/* chop off any /n or /r */
390 	while (*buf && is_crlf(*(*buf)->data)) {
391 		net_buf_pull_u8(*buf);
392 		if (!(*buf)->len) {
393 			*buf = net_buf_frag_del(NULL, *buf);
394 		}
395 	}
396 }
397 
net_buf_findcrlf(struct net_buf * buf,struct net_buf ** frag,uint16_t * offset)398 static uint16_t net_buf_findcrlf(struct net_buf *buf, struct net_buf **frag,
399 			      uint16_t *offset)
400 {
401 	uint16_t len = 0U, pos = 0U;
402 
403 	while (buf && !is_crlf(*(buf->data + pos))) {
404 		if (pos + 1 >= buf->len) {
405 			len += buf->len;
406 			buf = buf->frags;
407 			pos = 0U;
408 		} else {
409 			pos++;
410 		}
411 	}
412 
413 	if (buf && is_crlf(*(buf->data + pos))) {
414 		len += pos;
415 		*offset = pos;
416 		*frag = buf;
417 		return len;
418 	}
419 
420 	return 0;
421 }
422 
423 /*** UDP / TCP Helper Function ***/
424 
425 /* Setup IP header data to be used by some network applications.
426  * While much is dummy data, some fields such as dst, port and family are
427  * important.
428  * Return the IP + protocol header length.
429  */
pkt_setup_ip_data(struct net_pkt * pkt,struct wncm14a2a_socket * sock)430 static int pkt_setup_ip_data(struct net_pkt *pkt,
431 			     struct wncm14a2a_socket *sock)
432 {
433 	int hdr_len = 0;
434 	uint16_t src_port = 0U, dst_port = 0U;
435 
436 #if defined(CONFIG_NET_IPV6)
437 	if (net_pkt_family(pkt) == AF_INET6) {
438 		if (net_ipv6_create(
439 			    pkt,
440 			    &((struct sockaddr_in6 *)&sock->dst)->sin6_addr,
441 			    &((struct sockaddr_in6 *)&sock->src)->sin6_addr)) {
442 			return -1;
443 		}
444 		src_port = ntohs(net_sin6(&sock->src)->sin6_port);
445 		dst_port = ntohs(net_sin6(&sock->dst)->sin6_port);
446 
447 		hdr_len = sizeof(struct net_ipv6_hdr);
448 	} else
449 #endif
450 #if defined(CONFIG_NET_IPV4)
451 	if (net_pkt_family(pkt) == AF_INET) {
452 		if (net_ipv4_create(
453 			    pkt,
454 			    &((struct sockaddr_in *)&sock->dst)->sin_addr,
455 			    &((struct sockaddr_in *)&sock->src)->sin_addr)) {
456 			return -1;
457 		}
458 		src_port = ntohs(net_sin(&sock->src)->sin_port);
459 		dst_port = ntohs(net_sin(&sock->dst)->sin_port);
460 
461 		hdr_len = sizeof(struct net_ipv4_hdr);
462 	} else
463 #endif
464 	{
465 		/* no error here as hdr_len is checked later for 0 value */
466 	}
467 
468 #if defined(CONFIG_NET_UDP)
469 	if (sock->ip_proto == IPPROTO_UDP) {
470 		if (net_udp_create(pkt, dst_port, src_port)) {
471 			return -1;
472 		}
473 
474 		hdr_len += NET_UDPH_LEN;
475 	} else
476 #endif
477 #if defined(CONFIG_NET_TCP)
478 	if (sock->ip_proto == IPPROTO_TCP) {
479 		NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
480 		struct net_tcp_hdr *tcp;
481 
482 		tcp = (struct net_tcp_hdr *)net_pkt_get_data(pkt, &tcp_access);
483 		if (!tcp) {
484 			return -1;
485 		}
486 
487 		(void)memset(tcp, 0, NET_TCPH_LEN);
488 
489 		/* Setup TCP header */
490 		tcp->src_port = dst_port;
491 		tcp->dst_port = src_port;
492 
493 		if (net_pkt_set_data(pkt, &tcp_access)) {
494 			return -1;
495 		}
496 
497 		hdr_len += NET_TCPH_LEN;
498 	} else
499 #endif /* CONFIG_NET_TCP */
500 	{
501 		/* no error here as hdr_len is checked later for 0 value */
502 	}
503 
504 	return hdr_len;
505 }
506 
507 /*** MODEM RESPONSE HANDLERS ***/
508 
509 /* Last Socket ID Handler */
on_cmd_atcmdecho(struct net_buf ** buf,uint16_t len)510 static void on_cmd_atcmdecho(struct net_buf **buf, uint16_t len)
511 {
512 	char value[2];
513 	/* make sure only a single digit is picked up for socket_id */
514 	value[0] = net_buf_pull_u8(*buf);
515 	ictx.last_socket_id = atoi(value);
516 }
517 
518 /* Echo Handler for commands without related sockets */
on_cmd_atcmdecho_nosock(struct net_buf ** buf,uint16_t len)519 static void on_cmd_atcmdecho_nosock(struct net_buf **buf, uint16_t len)
520 {
521 	/* clear last_socket_id */
522 	ictx.last_socket_id = 0;
523 }
524 
on_cmd_atcmdinfo_manufacturer(struct net_buf ** buf,uint16_t len)525 static void on_cmd_atcmdinfo_manufacturer(struct net_buf **buf, uint16_t len)
526 {
527 	size_t out_len;
528 
529 	out_len = net_buf_linearize(ictx.mdm_manufacturer,
530 				    sizeof(ictx.mdm_manufacturer) - 1,
531 				    *buf, 0, len);
532 	ictx.mdm_manufacturer[out_len] = 0;
533 	LOG_INF("Manufacturer: %s", ictx.mdm_manufacturer);
534 }
535 
on_cmd_atcmdinfo_model(struct net_buf ** buf,uint16_t len)536 static void on_cmd_atcmdinfo_model(struct net_buf **buf, uint16_t len)
537 {
538 	size_t out_len;
539 
540 	out_len = net_buf_linearize(ictx.mdm_model,
541 				    sizeof(ictx.mdm_model) - 1,
542 				    *buf, 0, len);
543 	ictx.mdm_model[out_len] = 0;
544 	LOG_INF("Model: %s", ictx.mdm_model);
545 }
546 
on_cmd_atcmdinfo_revision(struct net_buf ** buf,uint16_t len)547 static void on_cmd_atcmdinfo_revision(struct net_buf **buf, uint16_t len)
548 {
549 	size_t out_len;
550 
551 	out_len = net_buf_linearize(ictx.mdm_revision,
552 				    sizeof(ictx.mdm_revision) - 1,
553 				    *buf, 0, len);
554 	ictx.mdm_revision[out_len] = 0;
555 	LOG_INF("Revision: %s", ictx.mdm_revision);
556 }
557 
on_cmd_atcmdecho_nosock_imei(struct net_buf ** buf,uint16_t len)558 static void on_cmd_atcmdecho_nosock_imei(struct net_buf **buf, uint16_t len)
559 {
560 	struct net_buf *frag = NULL;
561 	uint16_t offset;
562 	size_t out_len;
563 
564 	/* make sure IMEI data is received */
565 	if (len < MDM_IMEI_LENGTH) {
566 		LOG_DBG("Waiting for data");
567 		/* wait for more data */
568 		k_sleep(K_MSEC(500));
569 		wncm14a2a_read_rx(buf);
570 	}
571 
572 	net_buf_skipcrlf(buf);
573 	if (!*buf) {
574 		LOG_DBG("Unable to find IMEI (net_buf_skipcrlf)");
575 		return;
576 	}
577 
578 	frag = NULL;
579 	len = net_buf_findcrlf(*buf, &frag, &offset);
580 	if (!frag) {
581 		LOG_DBG("Unable to find IMEI (net_buf_findcrlf)");
582 		return;
583 	}
584 
585 	out_len = net_buf_linearize(ictx.mdm_imei, sizeof(ictx.mdm_imei) - 1,
586 				    *buf, 0, len);
587 	ictx.mdm_imei[out_len] = 0;
588 
589 	LOG_INF("IMEI: %s", ictx.mdm_imei);
590 }
591 
592 /* Handler: %MEAS: RSSI:Reported= -68, Ant0= -63, Ant1= -251 */
on_cmd_atcmdinfo_rssi(struct net_buf ** buf,uint16_t len)593 static void on_cmd_atcmdinfo_rssi(struct net_buf **buf, uint16_t len)
594 {
595 	int start = 0, i = 0;
596 	size_t value_size;
597 	char value[64];
598 
599 	value_size = sizeof(value);
600 	(void)memset(value, 0, value_size);
601 	while (*buf && len > 0 && i < value_size) {
602 		value[i] = net_buf_pull_u8(*buf);
603 		if (!(*buf)->len) {
604 			*buf = net_buf_frag_del(NULL, *buf);
605 		}
606 
607 		/* 2nd "=" marks the beginning of the RSSI value */
608 		if (start < 2) {
609 			if (value[i] == '=') {
610 				start++;
611 			}
612 
613 			continue;
614 		}
615 
616 		/* "," marks the end of the RSSI value */
617 		if (value[i] == ',') {
618 			value[i] = '\0';
619 			break;
620 		}
621 
622 		i++;
623 	}
624 
625 	if (i > 0) {
626 		ictx.mdm_rssi = atoi(value);
627 		LOG_INF("RSSI: %d", ictx.mdm_rssi);
628 	} else {
629 		LOG_WRN("Bad format found for RSSI");
630 	}
631 }
632 
633 /* Handler: OK */
on_cmd_sockok(struct net_buf ** buf,uint16_t len)634 static void on_cmd_sockok(struct net_buf **buf, uint16_t len)
635 {
636 	struct wncm14a2a_socket *sock = NULL;
637 
638 	ictx.last_error = 0;
639 	sock = socket_from_id(ictx.last_socket_id);
640 	if (!sock) {
641 		k_sem_give(&ictx.response_sem);
642 	} else {
643 		k_sem_give(&sock->sock_send_sem);
644 	}
645 }
646 
647 /* Handler: ERROR */
on_cmd_sockerror(struct net_buf ** buf,uint16_t len)648 static void on_cmd_sockerror(struct net_buf **buf, uint16_t len)
649 {
650 	struct wncm14a2a_socket *sock = NULL;
651 
652 	ictx.last_error = -EIO;
653 	sock = socket_from_id(ictx.last_socket_id);
654 	if (!sock) {
655 		k_sem_give(&ictx.response_sem);
656 	} else {
657 		k_sem_give(&sock->sock_send_sem);
658 	}
659 }
660 
661 /* Handler: @EXTERR:<exterror_id> */
on_cmd_sockexterror(struct net_buf ** buf,uint16_t len)662 static void on_cmd_sockexterror(struct net_buf **buf, uint16_t len)
663 {
664 	char value[8];
665 	size_t out_len;
666 
667 	struct wncm14a2a_socket *sock = NULL;
668 
669 	out_len = net_buf_linearize(value, sizeof(value) - 1, *buf, 0, len);
670 	value[out_len] = 0;
671 	ictx.last_error = -atoi(value);
672 	LOG_ERR("@EXTERR:%d", ictx.last_error);
673 	sock = socket_from_id(ictx.last_socket_id);
674 	if (!sock) {
675 		k_sem_give(&ictx.response_sem);
676 	} else {
677 		k_sem_give(&sock->sock_send_sem);
678 	}
679 }
680 
681 /* Handler: @SOCKDIAL:<status> */
on_cmd_sockdial(struct net_buf ** buf,uint16_t len)682 static void on_cmd_sockdial(struct net_buf **buf, uint16_t len)
683 {
684 	char value[8];
685 	size_t out_len;
686 
687 	out_len = net_buf_linearize(value, sizeof(value) - 1, *buf, 0, len);
688 	value[out_len] = 0;
689 	ictx.last_error = atoi(value);
690 	k_sem_give(&ictx.response_sem);
691 }
692 
693 /* Handler: @SOCKCREAT:<socket_id> */
on_cmd_sockcreat(struct net_buf ** buf,uint16_t len)694 static void on_cmd_sockcreat(struct net_buf **buf, uint16_t len)
695 {
696 	char value[2];
697 	struct wncm14a2a_socket *sock = NULL;
698 
699 	/* look up new socket by special id */
700 	sock = socket_from_id(MDM_MAX_SOCKETS + 1);
701 	if (sock) {
702 	/* make sure only a single digit is picked up for socket_id */
703 		value[0] = net_buf_pull_u8(*buf);
704 		sock->socket_id = atoi(value);
705 	}
706 	/* don't give back semaphore -- OK to follow */
707 }
708 
709 /* Handler: @SOCKWRITE:<actual_length> */
on_cmd_sockwrite(struct net_buf ** buf,uint16_t len)710 static void on_cmd_sockwrite(struct net_buf **buf, uint16_t len)
711 {
712 	char value[8];
713 	size_t out_len;
714 	int write_len;
715 	struct wncm14a2a_socket *sock = NULL;
716 
717 	/* TODO: check against what we wanted to send */
718 	out_len = net_buf_linearize(value, sizeof(value) - 1, *buf, 0, len);
719 	value[out_len] = 0;
720 	write_len = atoi(value);
721 	if (write_len <= 0) {
722 		return;
723 	}
724 
725 	sock = socket_from_id(ictx.last_socket_id);
726 	if (sock) {
727 		k_sem_give(&sock->sock_send_sem);
728 	}
729 }
730 
sockreadrecv_cb_work(struct k_work * work)731 static void sockreadrecv_cb_work(struct k_work *work)
732 {
733 	struct wncm14a2a_socket *sock = NULL;
734 	struct net_pkt *pkt;
735 
736 	sock = CONTAINER_OF(work, struct wncm14a2a_socket, recv_cb_work);
737 
738 	/* return data */
739 	pkt = sock->recv_pkt;
740 	sock->recv_pkt = NULL;
741 	if (sock->recv_cb) {
742 		sock->recv_cb(sock->context, pkt, NULL, NULL,
743 			      0, sock->recv_user_data);
744 	} else {
745 		net_pkt_unref(pkt);
746 	}
747 }
748 
749 /* Handler: @SOCKREAD:<actual_length>,"<hex encoded binary>" */
on_cmd_sockread(struct net_buf ** buf,uint16_t len)750 static void on_cmd_sockread(struct net_buf **buf, uint16_t len)
751 {
752 	struct wncm14a2a_socket *sock = NULL;
753 	uint8_t c = 0U;
754 	int i, actual_length, hdr_len = 0;
755 	size_t value_size;
756 	char value[10];
757 
758 	/* first comma marks the end of actual_length */
759 	i = 0;
760 	value_size = sizeof(value);
761 	(void)memset(value, 0, value_size);
762 	while (*buf && i < value_size - 1) {
763 		value[i++] = net_buf_pull_u8(*buf);
764 		len--;
765 		if (!(*buf)->len) {
766 			*buf = net_buf_frag_del(NULL, *buf);
767 		}
768 
769 		if (value[i-1] == ',') {
770 			i--;
771 			break;
772 		}
773 	}
774 
775 	/* make sure we still have buf data, the last pulled character was
776 	 * a comma and that the next char in the buffer is a quote.
777 	 */
778 	if (!*buf || value[i] != ',' || *(*buf)->data != '\"') {
779 		LOG_ERR("Incorrect format! Ignoring data!");
780 		return;
781 	}
782 
783 	/* clear the comma */
784 	value[i] = '\0';
785 	actual_length = atoi(value);
786 
787 	/* skip quote */
788 	len--;
789 	net_buf_pull_u8(*buf);
790 	if (!(*buf)->len) {
791 		*buf = net_buf_frag_del(NULL, *buf);
792 	}
793 
794 	/* check that we have enough data */
795 	if (!*buf || len > (actual_length * 2) + 1) {
796 		LOG_ERR("Incorrect format! Ignoring data!");
797 		return;
798 	}
799 
800 	sock = socket_from_id(ictx.last_socket_id);
801 	if (!sock) {
802 		LOG_ERR("Socket not found! (%d)", ictx.last_socket_id);
803 		return;
804 	}
805 
806 	/* allocate an RX pkt */
807 	sock->recv_pkt = net_pkt_rx_alloc_with_buffer(
808 			net_context_get_iface(sock->context),
809 			actual_length, sock->family, sock->ip_proto,
810 			BUF_ALLOC_TIMEOUT);
811 	if (!sock->recv_pkt) {
812 		LOG_ERR("Failed net_pkt_get_reserve_rx!");
813 		return;
814 	}
815 
816 	/* set pkt data */
817 	net_pkt_set_context(sock->recv_pkt, sock->context);
818 
819 	/* add IP / protocol headers */
820 	hdr_len = pkt_setup_ip_data(sock->recv_pkt, sock);
821 
822 	/* move hex encoded data from the buffer to the recv_pkt */
823 	for (i = 0; i < actual_length * 2; i++) {
824 		char c2 = *(*buf)->data;
825 
826 		if (isdigit((int)c2) != 0) {
827 			c += c2 - '0';
828 		} else if (isalpha((int)c2) != 0) {
829 			c += c2 - (isupper((int)c2) != 0 ? 'A' - 10 : 'a' - 10);
830 		} else {
831 			/* TODO: unexpected input! skip? */
832 		}
833 
834 		if (i % 2) {
835 			if (net_pkt_write_u8(sock->recv_pkt, c)) {
836 				LOG_ERR("Unable to add data! Aborting!");
837 				net_pkt_unref(sock->recv_pkt);
838 				sock->recv_pkt = NULL;
839 				return;
840 			}
841 
842 			c = 0U;
843 		} else {
844 			c = c << 4;
845 		}
846 
847 		/* pull data from buf and advance to the next frag if needed */
848 		net_buf_pull_u8(*buf);
849 		if (!(*buf)->len) {
850 			*buf = net_buf_frag_del(NULL, *buf);
851 		}
852 	}
853 
854 	net_pkt_cursor_init(sock->recv_pkt);
855 	net_pkt_set_overwrite(sock->recv_pkt, true);
856 
857 	if (hdr_len > 0) {
858 		net_pkt_skip(sock->recv_pkt, hdr_len);
859 	}
860 
861 	/* Let's do the callback processing in a different work queue in
862 	 * case the app takes a long time.
863 	 */
864 	k_work_submit_to_queue(&wncm14a2a_workq, &sock->recv_cb_work);
865 }
866 
867 /* Handler: @SOCKDATAIND: <socket_id>,<session_status>,<left_bytes> */
on_cmd_sockdataind(struct net_buf ** buf,uint16_t len)868 static void on_cmd_sockdataind(struct net_buf **buf, uint16_t len)
869 {
870 	int socket_id, left_bytes;
871 	size_t out_len;
872 	char *delim1, *delim2;
873 	char value[sizeof("#,#,#####\r")];
874 	char sendbuf[sizeof("AT@SOCKREAD=-#####,-#####\r")];
875 	struct wncm14a2a_socket *sock = NULL;
876 
877 	out_len = net_buf_linearize(value, sizeof(value) - 1, *buf, 0, len);
878 	value[out_len] = 0;
879 
880 	/* First comma separator marks the end of socket_id */
881 	delim1 = strchr(value, ',');
882 	if (!delim1) {
883 		LOG_ERR("Missing 1st comma");
884 		return;
885 	}
886 
887 	*delim1++ = '\0';
888 	socket_id = atoi(value);
889 
890 	/* Second comma separator marks the end of session_status */
891 	/* TODO: ignore for now, but maybe this is useful? */
892 	delim2 = strchr(delim1, ',');
893 	if (!delim2) {
894 		LOG_ERR("Missing 2nd comma");
895 		return;
896 	}
897 
898 	*delim2++ = '\0';
899 
900 	/* Third param is for left_bytes */
901 	/* TODO: ignore for now because we ask for max data len
902 	 * but maybe this is useful in the future?
903 	 */
904 	left_bytes = atoi(delim2);
905 
906 	sock = socket_from_id(socket_id);
907 	if (!sock) {
908 		LOG_ERR("Unable to find socket_id:%d", socket_id);
909 		return;
910 	}
911 
912 	if (left_bytes > 0) {
913 		LOG_DBG("socket_id:%d left_bytes:%d", socket_id, left_bytes);
914 		snprintk(sendbuf, sizeof(sendbuf), "AT@SOCKREAD=%d,%d",
915 			 sock->socket_id, left_bytes);
916 
917 		/* We entered this trigger due to an unsolicited modem response.
918 		 * When we send the AT@SOCKREAD command it won't generate an
919 		 * "OK" response directly.  The modem will respond with
920 		 * "@SOCKREAD ..." and the data requested and then "OK" or
921 		 * "ERROR".  Let's not wait here by passing in a timeout to
922 		 * send_at_cmd().  Instead, when the resulting response is
923 		 * received, we trigger on_cmd_sockread() to handle it.
924 		 */
925 		send_at_cmd(sock, sendbuf, 0);
926 	}
927 }
928 
on_cmd_socknotifyev(struct net_buf ** buf,uint16_t len)929 static void on_cmd_socknotifyev(struct net_buf **buf, uint16_t len)
930 {
931 	char value[40];
932 	size_t out_len;
933 	int p1 = 0, p2 = 0;
934 
935 	out_len = net_buf_linearize(value, sizeof(value) - 1, *buf, 0, len);
936 	value[out_len] = 0;
937 
938 	/* walk value till 1st quote */
939 	while (p1 < len && value[p1] != '\"') {
940 		p1++;
941 	}
942 
943 	if (value[p1] != '\"') {
944 		/* 1st quote not found */
945 		return;
946 	}
947 
948 	p1++;
949 	p2 = p1;
950 	while (p2 < len && value[p2] != '\"') {
951 		p2++;
952 	}
953 
954 	if (value[p2] != '\"') {
955 		/* 2nd quote not found */
956 		return;
957 	}
958 
959 	/* clear quote */
960 	value[p2] = '\0';
961 	p2++;
962 
963 	/* skip comma if present */
964 	if (value[p2] == ',') {
965 		p2++;
966 	}
967 
968 	/* CSPS: 0: Moved to PS mode, 1: Moved to CS/PS mode */
969 	if (!strncmp(&value[p1], "CSPS", 4)) {
970 		ictx.ev_csps = atoi(&value[p2]);
971 		/* This also signifies that RRCSTATE = 1 */
972 		ictx.ev_rrcstate = 1;
973 		LOG_DBG("CSPS:%d", ictx.ev_csps);
974 	/* RRCSTATE: 0: RRC Idle, 1: RRC Connected, 2: RRC Unknown */
975 	} else if (!strncmp(&value[p1], "RRCSTATE", 8)) {
976 		ictx.ev_rrcstate = atoi(&value[p2]);
977 		LOG_DBG("RRCSTATE:%d", ictx.ev_rrcstate);
978 	} else if (!strncmp(&value[p1], "LTIME", 5)) {
979 		/* local time from network */
980 		LOG_INF("LTIME:%s", &value[p2]);
981 	} else if (!strncmp(&value[p1], "SIB1", 4)) {
982 		/* do nothing? */
983 		LOG_DBG("SIB1");
984 	} else {
985 		LOG_DBG("UNHANDLED: [%s:%s]", &value[p1], &value[p2]);
986 	}
987 }
988 
net_buf_ncmp(struct net_buf * buf,const uint8_t * s2,size_t n)989 static int net_buf_ncmp(struct net_buf *buf, const uint8_t *s2, size_t n)
990 {
991 	struct net_buf *frag = buf;
992 	uint16_t offset = 0U;
993 
994 	while ((n > 0) && (*(frag->data + offset) == *s2) && (*s2 != '\0')) {
995 		if (offset == frag->len) {
996 			if (!frag->frags) {
997 				break;
998 			}
999 			frag = frag->frags;
1000 			offset = 0U;
1001 		} else {
1002 			offset++;
1003 		}
1004 
1005 		s2++;
1006 		n--;
1007 	}
1008 
1009 	return (n == 0) ? 0 : (*(frag->data + offset) - *s2);
1010 }
1011 
read_rx_allocator(k_timeout_t timeout,void * user_data)1012 static inline struct net_buf *read_rx_allocator(k_timeout_t timeout,
1013 						void *user_data)
1014 {
1015 	return net_buf_alloc((struct net_buf_pool *)user_data, timeout);
1016 }
1017 
wncm14a2a_read_rx(struct net_buf ** buf)1018 static void wncm14a2a_read_rx(struct net_buf **buf)
1019 {
1020 	uint8_t uart_buffer[MDM_RECV_BUF_SIZE];
1021 	size_t bytes_read = 0;
1022 	int ret;
1023 	uint16_t rx_len;
1024 
1025 	/* read all of the data from mdm_receiver */
1026 	while (true) {
1027 		ret = mdm_receiver_recv(&ictx.mdm_ctx,
1028 					uart_buffer,
1029 					sizeof(uart_buffer),
1030 					&bytes_read);
1031 		if (ret < 0 || bytes_read == 0) {
1032 			/* mdm_receiver buffer is empty */
1033 			break;
1034 		}
1035 
1036 		hexdump(uart_buffer, bytes_read);
1037 
1038 		/* make sure we have storage */
1039 		if (!*buf) {
1040 			*buf = net_buf_alloc(&mdm_recv_pool, BUF_ALLOC_TIMEOUT);
1041 			if (!*buf) {
1042 				LOG_ERR("Can't allocate RX data! "
1043 					    "Skipping data!");
1044 				break;
1045 			}
1046 		}
1047 
1048 		rx_len = net_buf_append_bytes(*buf, bytes_read, uart_buffer,
1049 					      BUF_ALLOC_TIMEOUT,
1050 					      read_rx_allocator,
1051 					      &mdm_recv_pool);
1052 		if (rx_len < bytes_read) {
1053 			LOG_ERR("Data was lost! read %u of %zu!",
1054 				    rx_len, bytes_read);
1055 		}
1056 	}
1057 }
1058 
1059 /* RX thread */
wncm14a2a_rx(void * p1,void * p2,void * p3)1060 static void wncm14a2a_rx(void *p1, void *p2, void *p3)
1061 {
1062 	ARG_UNUSED(p1);
1063 	ARG_UNUSED(p2);
1064 	ARG_UNUSED(p3);
1065 
1066 	struct net_buf *rx_buf = NULL;
1067 	struct net_buf *frag = NULL;
1068 	int i;
1069 	uint16_t offset, len;
1070 
1071 	static const struct cmd_handler handlers[] = {
1072 		/* NON-SOCKET COMMAND ECHOES to clear last_socket_id */
1073 		CMD_HANDLER("ATE1", atcmdecho_nosock),
1074 		CMD_HANDLER("AT%PDNSET=", atcmdecho_nosock),
1075 		CMD_HANDLER("ATI", atcmdecho_nosock),
1076 		CMD_HANDLER("AT+CGSN", atcmdecho_nosock_imei),
1077 		CMD_HANDLER("AT%MEAS=", atcmdecho_nosock),
1078 		CMD_HANDLER("AT@INTERNET=", atcmdecho_nosock),
1079 		CMD_HANDLER("AT@SOCKDIAL=", atcmdecho_nosock),
1080 		CMD_HANDLER("AT@SOCKCREAT=", atcmdecho_nosock),
1081 
1082 		/* SOCKET COMMAND ECHOES for last_socket_id processing */
1083 		CMD_HANDLER("AT@SOCKCONN=", atcmdecho),
1084 		CMD_HANDLER("AT@SOCKWRITE=", atcmdecho),
1085 		CMD_HANDLER("AT@SOCKREAD=", atcmdecho),
1086 		CMD_HANDLER("AT@SOCKCLOSE=", atcmdecho),
1087 
1088 		/* MODEM Information */
1089 		CMD_HANDLER("Manufacturer: ", atcmdinfo_manufacturer),
1090 		CMD_HANDLER("Model: ", atcmdinfo_model),
1091 		CMD_HANDLER("Revision: ", atcmdinfo_revision),
1092 		CMD_HANDLER("%MEAS: RSSI:", atcmdinfo_rssi),
1093 
1094 		/* SOLICITED SOCKET RESPONSES */
1095 		CMD_HANDLER("OK", sockok),
1096 		CMD_HANDLER("ERROR", sockerror),
1097 		CMD_HANDLER("@EXTERR:", sockexterror),
1098 		CMD_HANDLER("@SOCKDIAL:", sockdial),
1099 		CMD_HANDLER("@SOCKCREAT:", sockcreat),
1100 		CMD_HANDLER("@OCKCREAT:", sockcreat), /* seeing this a lot */
1101 		CMD_HANDLER("@SOCKWRITE:", sockwrite),
1102 		CMD_HANDLER("@SOCKREAD:", sockread),
1103 
1104 		/* UNSOLICITED SOCKET RESPONSES */
1105 		CMD_HANDLER("@SOCKDATAIND:", sockdataind),
1106 		CMD_HANDLER("%NOTIFYEV:", socknotifyev),
1107 	};
1108 
1109 	while (true) {
1110 		/* wait for incoming data */
1111 		(void)k_sem_take(&ictx.mdm_ctx.rx_sem, K_FOREVER);
1112 
1113 		wncm14a2a_read_rx(&rx_buf);
1114 
1115 		while (rx_buf) {
1116 			net_buf_skipcrlf(&rx_buf);
1117 			if (!rx_buf) {
1118 				break;
1119 			}
1120 
1121 			frag = NULL;
1122 			len = net_buf_findcrlf(rx_buf, &frag, &offset);
1123 			if (!frag) {
1124 				break;
1125 			}
1126 
1127 			/* look for matching data handlers */
1128 			i = -1;
1129 			for (i = 0; i < ARRAY_SIZE(handlers); i++) {
1130 				if (net_buf_ncmp(rx_buf, handlers[i].cmd,
1131 						 handlers[i].cmd_len) == 0) {
1132 					/* found a matching handler */
1133 					LOG_DBG("MATCH %s (len:%u)",
1134 						    handlers[i].cmd, len);
1135 
1136 					/* skip cmd_len */
1137 					rx_buf = net_buf_skip(rx_buf,
1138 							handlers[i].cmd_len);
1139 
1140 					/* locate next cr/lf */
1141 					frag = NULL;
1142 					len = net_buf_findcrlf(rx_buf,
1143 							       &frag, &offset);
1144 					if (!frag) {
1145 						break;
1146 					}
1147 
1148 					/* call handler */
1149 					if (handlers[i].func) {
1150 						handlers[i].func(&rx_buf, len);
1151 					}
1152 
1153 					frag = NULL;
1154 					/* make sure buf still has data */
1155 					if (!rx_buf) {
1156 						break;
1157 					}
1158 
1159 					/*
1160 					 * We've handled the current line
1161 					 * and need to exit the "search for
1162 					 * handler loop".  Let's skip any
1163 					 * "extra" data and look for the next
1164 					 * CR/LF, leaving us ready for the
1165 					 * next handler search.  Ignore the
1166 					 * length returned.
1167 					 */
1168 					(void)net_buf_findcrlf(rx_buf,
1169 							       &frag, &offset);
1170 					break;
1171 				}
1172 			}
1173 
1174 			if (frag && rx_buf) {
1175 				/* clear out processed line (buffers) */
1176 				while (frag && rx_buf != frag) {
1177 					rx_buf = net_buf_frag_del(NULL, rx_buf);
1178 				}
1179 
1180 				net_buf_pull(rx_buf, offset);
1181 			}
1182 		}
1183 
1184 		/* give up time if we have a solid stream of data */
1185 		k_yield();
1186 	}
1187 }
1188 
modem_pin_init(void)1189 static int modem_pin_init(void)
1190 {
1191 	LOG_INF("Setting Modem Pins");
1192 
1193 	/* Hard reset the modem (>5 seconds required)
1194 	 * (doesn't go through the signal level translator)
1195 	 */
1196 	LOG_DBG("MDM_RESET_PIN -> ASSERTED");
1197 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_RESET], 1);
1198 	k_sleep(K_SECONDS(7));
1199 	LOG_DBG("MDM_RESET_PIN -> NOT_ASSERTED");
1200 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_RESET], 0);
1201 
1202 	/* disable signal level translator (necessary
1203 	 * for the modem to boot properly).  All signals
1204 	 * except mdm_reset go through the level translator
1205 	 * and have internal pull-up/down in the module. While
1206 	 * the level translator is disabled, these pins will
1207 	 * be in the correct state.
1208 	 */
1209 	LOG_DBG("SIG_TRANS_ENA_PIN -> DISABLED");
1210 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[SHLD_3V3_1V8_SIG_TRANS_ENA], 0);
1211 
1212 	/* While the level translator is disabled and output pins
1213 	 * are tristated, make sure the inputs are in the same state
1214 	 * as the WNC Module pins so that when the level translator is
1215 	 * enabled, there are no differences.
1216 	 */
1217 	LOG_DBG("MDM_BOOT_MODE_SEL_PIN -> NORMAL");
1218 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_BOOT_MODE_SEL], MDM_BOOT_MODE_NORMAL);
1219 	LOG_DBG("MDM_POWER_PIN -> ENABLE");
1220 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_POWER], 1);
1221 	LOG_DBG("MDM_KEEP_AWAKE_PIN -> ENABLED");
1222 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_KEEP_AWAKE], 1);
1223 #if DT_INST_NODE_HAS_PROP(0, mdm_send_ok_gpios)
1224 	LOG_DBG("MDM_SEND_OK_PIN -> ENABLED");
1225 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_SEND_OK], 1);
1226 #endif
1227 
1228 	/* wait for the WNC Module to perform its initial boot correctly */
1229 	k_sleep(K_SECONDS(1));
1230 
1231 	/* Enable the level translator.
1232 	 * The input pins should now be the same as how the M14A module is
1233 	 * driving them with internal pull ups/downs.
1234 	 * When enabled, there will be no changes in the above 4 pins...
1235 	 */
1236 	LOG_DBG("SIG_TRANS_ENA_PIN -> ENABLED");
1237 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[SHLD_3V3_1V8_SIG_TRANS_ENA], 1);
1238 
1239 	LOG_INF("... Done!");
1240 
1241 	return 0;
1242 }
1243 
modem_wakeup_pin_fix(void)1244 static void modem_wakeup_pin_fix(void)
1245 {
1246 	/* AT&T recommend toggling the KEEP_AWAKE signal to reduce missed
1247 	 * UART characters.
1248 	 */
1249 	LOG_DBG("Toggling MDM_KEEP_AWAKE_PIN to avoid missed characters");
1250 	k_sleep(K_MSEC(20));
1251 	LOG_DBG("MDM_KEEP_AWAKE_PIN -> DISABLED");
1252 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_KEEP_AWAKE], 0);
1253 	k_sleep(K_SECONDS(2));
1254 	LOG_DBG("MDM_KEEP_AWAKE_PIN -> ENABLED");
1255 	gpio_pin_set_dt(&wncm14a2a_cfg.gpio[MDM_KEEP_AWAKE], 1);
1256 	k_sleep(K_MSEC(20));
1257 }
1258 
wncm14a2a_rssi_query_work(struct k_work * work)1259 static void wncm14a2a_rssi_query_work(struct k_work *work)
1260 {
1261 	int ret;
1262 
1263 	/* query modem RSSI */
1264 	ret = send_at_cmd(NULL, "AT%MEAS=\"23\"", MDM_CMD_TIMEOUT);
1265 	if (ret < 0) {
1266 		LOG_ERR("AT%%MEAS ret:%d", ret);
1267 	}
1268 
1269 	/* re-start RSSI query work */
1270 	k_work_reschedule_for_queue(&wncm14a2a_workq, &ictx.rssi_query_work,
1271 				    K_SECONDS(RSSI_TIMEOUT_SECS));
1272 }
1273 
wncm14a2a_modem_reset(void)1274 static void wncm14a2a_modem_reset(void)
1275 {
1276 	int ret = 0, retry_count = 0, counter = 0;
1277 
1278 	/* bring down network interface */
1279 	net_if_carrier_off(ictx.iface);
1280 
1281 restart:
1282 	/* stop RSSI delay work */
1283 	k_work_cancel_delayable(&ictx.rssi_query_work);
1284 
1285 	modem_pin_init();
1286 
1287 	LOG_INF("Waiting for modem to respond");
1288 
1289 	/* Give the modem a while to start responding to simple 'AT' commands.
1290 	 * Also wait for CSPS=1 or RRCSTATE=1 notification
1291 	 */
1292 	ret = -1;
1293 	while (counter++ < 50 && ret < 0) {
1294 		k_sleep(K_SECONDS(2));
1295 		ret = send_at_cmd(NULL, "AT", MDM_CMD_TIMEOUT);
1296 		if (ret < 0 && ret != -ETIMEDOUT) {
1297 			break;
1298 		}
1299 	}
1300 
1301 	if (ret < 0) {
1302 		LOG_ERR("MODEM WAIT LOOP ERROR: %d", ret);
1303 		goto error;
1304 	}
1305 
1306 	LOG_INF("Setting modem to always stay awake");
1307 	modem_wakeup_pin_fix();
1308 
1309 	ret = send_at_cmd(NULL, "ATE1", MDM_CMD_TIMEOUT);
1310 	if (ret < 0) {
1311 		LOG_ERR("ATE1 ret:%d", ret);
1312 		goto error;
1313 	}
1314 
1315 	ret = send_at_cmd(NULL, "AT%PDNSET=1,\"" CONFIG_MODEM_WNCM14A2A_APN_NAME
1316 			  "\",\"IPV4V6\"", MDM_CMD_TIMEOUT);
1317 	if (ret < 0) {
1318 		LOG_ERR("AT%%PDNSET ret:%d", ret);
1319 		goto error;
1320 	}
1321 
1322 	/* query modem info */
1323 	LOG_INF("Querying modem information");
1324 	ret = send_at_cmd(NULL, "ATI", MDM_CMD_TIMEOUT);
1325 	if (ret < 0) {
1326 		LOG_ERR("ATI ret:%d", ret);
1327 		goto error;
1328 	}
1329 
1330 	/* query modem IMEI */
1331 	ret = send_at_cmd(NULL, "AT+CGSN", MDM_CMD_TIMEOUT);
1332 	if (ret < 0) {
1333 		LOG_ERR("AT+CGSN ret:%d", ret);
1334 		goto error;
1335 	}
1336 
1337 	LOG_INF("Waiting for network");
1338 
1339 	/* query modem RSSI */
1340 	wncm14a2a_rssi_query_work(NULL);
1341 	k_sleep(K_SECONDS(2));
1342 
1343 	counter = 0;
1344 	/* wait for RSSI > -1000 and != 0 */
1345 	while (counter++ < 15 &&
1346 	       (ictx.mdm_rssi <= -1000 ||
1347 		ictx.mdm_rssi == 0)) {
1348 		/* stop RSSI delay work */
1349 		k_work_cancel_delayable(&ictx.rssi_query_work);
1350 		wncm14a2a_rssi_query_work(NULL);
1351 		k_sleep(K_SECONDS(2));
1352 	}
1353 
1354 	if (ictx.mdm_rssi <= -1000 || ictx.mdm_rssi == 0) {
1355 		retry_count++;
1356 		if (retry_count > 3) {
1357 			LOG_ERR("Failed network init.  Too many attempts!");
1358 			goto error;
1359 		}
1360 
1361 		LOG_ERR("Failed network init.  Restarting process.");
1362 		goto restart;
1363 	}
1364 
1365 	LOG_INF("Network is ready.");
1366 
1367 	ret = send_at_cmd(NULL, "AT@INTERNET=1", MDM_CMD_TIMEOUT);
1368 	if (ret < 0) {
1369 		LOG_ERR("AT@INTERNET ret:%d", ret);
1370 		goto error;
1371 	}
1372 
1373 	ret = send_at_cmd(NULL, "AT@SOCKDIAL=1", MDM_CMD_TIMEOUT);
1374 	if (ret < 0) {
1375 		LOG_ERR("SOCKDIAL=1 CHECK ret:%d", ret);
1376 		/* don't report this as an error, we retry later */
1377 	}
1378 
1379 	/* Set iface up */
1380 	net_if_carrier_on(ictx.iface);
1381 
1382 error:
1383 	return;
1384 }
1385 
wncm14a2a_init(const struct device * dev)1386 static int wncm14a2a_init(const struct device *dev)
1387 {
1388 	int i, ret = 0;
1389 
1390 	ARG_UNUSED(dev);
1391 
1392 	(void)memset(&ictx, 0, sizeof(ictx));
1393 	for (i = 0; i < MDM_MAX_SOCKETS; i++) {
1394 		k_work_init(&ictx.sockets[i].recv_cb_work,
1395 			    sockreadrecv_cb_work);
1396 		k_sem_init(&ictx.sockets[i].sock_send_sem, 0, 1);
1397 	}
1398 	k_sem_init(&ictx.response_sem, 0, 1);
1399 
1400 	/* initialize the work queue */
1401 	k_work_queue_start(&wncm14a2a_workq, wncm14a2a_workq_stack,
1402 			   K_KERNEL_STACK_SIZEOF(wncm14a2a_workq_stack),
1403 			   K_PRIO_COOP(7), NULL);
1404 
1405 	ictx.last_socket_id = 0;
1406 
1407 	/* setup port devices and pin directions */
1408 	for (i = 0; i < MAX_MDM_CONTROL_PINS; i++) {
1409 		if (!gpio_is_ready_dt(&wncm14a2a_cfg.gpio[i])) {
1410 			LOG_ERR("gpio port (%s) not ready!",
1411 				wncm14a2a_cfg.gpio[i].port->name);
1412 			return -ENODEV;
1413 		}
1414 
1415 		gpio_pin_configure_dt(&wncm14a2a_cfg.gpio[i], GPIO_OUTPUT);
1416 	}
1417 
1418 	/* Set modem data storage */
1419 	ictx.mdm_ctx.data_manufacturer = ictx.mdm_manufacturer;
1420 	ictx.mdm_ctx.data_model = ictx.mdm_model;
1421 	ictx.mdm_ctx.data_revision = ictx.mdm_revision;
1422 #ifdef CONFIG_MODEM_SIM_NUMBERS
1423 	ictx.mdm_ctx.data_imei = ictx.mdm_imei;
1424 #endif
1425 	ictx.mdm_ctx.data_rssi = &ictx.mdm_rssi;
1426 
1427 	ret = mdm_receiver_register(&ictx.mdm_ctx, MDM_UART_DEV,
1428 				    mdm_recv_buf, sizeof(mdm_recv_buf));
1429 	if (ret < 0) {
1430 		LOG_ERR("Error registering modem receiver (%d)!", ret);
1431 		goto error;
1432 	}
1433 
1434 	/* start RX thread */
1435 	k_thread_create(&wncm14a2a_rx_thread, wncm14a2a_rx_stack,
1436 			K_KERNEL_STACK_SIZEOF(wncm14a2a_rx_stack),
1437 			wncm14a2a_rx,
1438 			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
1439 
1440 	/* init RSSI query */
1441 	k_work_init_delayable(&ictx.rssi_query_work, wncm14a2a_rssi_query_work);
1442 
1443 	wncm14a2a_modem_reset();
1444 
1445 error:
1446 	return ret;
1447 }
1448 
1449 /*** OFFLOAD FUNCTIONS ***/
1450 
offload_get(sa_family_t family,enum net_sock_type type,enum net_ip_protocol ip_proto,struct net_context ** context)1451 static int offload_get(sa_family_t family,
1452 		       enum net_sock_type type,
1453 		       enum net_ip_protocol ip_proto,
1454 		       struct net_context **context)
1455 {
1456 	int ret;
1457 	char buf[sizeof("AT@SOCKCREAT=###,#\r")];
1458 	struct wncm14a2a_socket *sock = NULL;
1459 
1460 	/* new socket */
1461 	sock = socket_get();
1462 	if (!sock) {
1463 		return -ENOMEM;
1464 	}
1465 
1466 	(*context)->offload_context = sock;
1467 	sock->family = family;
1468 	sock->type = type;
1469 	sock->ip_proto = ip_proto;
1470 	sock->context = *context;
1471 	sock->socket_id = MDM_MAX_SOCKETS + 1; /* socket # needs assigning */
1472 
1473 	snprintk(buf, sizeof(buf), "AT@SOCKCREAT=%d,%d", type,
1474 		 family == AF_INET ? 0 : 1);
1475 	ret = send_at_cmd(NULL, buf, MDM_CMD_TIMEOUT);
1476 	if (ret < 0) {
1477 		LOG_ERR("AT@SOCKCREAT ret:%d", ret);
1478 		socket_put(sock);
1479 	}
1480 
1481 	return ret;
1482 }
1483 
offload_bind(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen)1484 static int offload_bind(struct net_context *context,
1485 			const struct sockaddr *addr,
1486 			socklen_t addrlen)
1487 {
1488 	struct wncm14a2a_socket *sock = NULL;
1489 
1490 	if (!context) {
1491 		return -EINVAL;
1492 	}
1493 
1494 	sock = (struct wncm14a2a_socket *)context->offload_context;
1495 	if (!sock) {
1496 		LOG_ERR("Can't locate socket for net_ctx:%p!", context);
1497 		return -EINVAL;
1498 	}
1499 
1500 	/* save bind address information */
1501 	sock->src.sa_family = addr->sa_family;
1502 #if defined(CONFIG_NET_IPV6)
1503 	if (addr->sa_family == AF_INET6) {
1504 		net_ipaddr_copy(&net_sin6(&sock->src)->sin6_addr,
1505 				&net_sin6(addr)->sin6_addr);
1506 		net_sin6(&sock->src)->sin6_port = net_sin6(addr)->sin6_port;
1507 	} else
1508 #endif
1509 #if defined(CONFIG_NET_IPV4)
1510 	if (addr->sa_family == AF_INET) {
1511 		net_ipaddr_copy(&net_sin(&sock->src)->sin_addr,
1512 				&net_sin(addr)->sin_addr);
1513 		net_sin(&sock->src)->sin_port = net_sin(addr)->sin_port;
1514 	} else
1515 #endif
1516 	{
1517 		return -EPFNOSUPPORT;
1518 	}
1519 
1520 	return 0;
1521 }
1522 
offload_listen(struct net_context * context,int backlog)1523 static int offload_listen(struct net_context *context, int backlog)
1524 {
1525 	/* NOT IMPLEMENTED */
1526 	return -ENOTSUP;
1527 }
1528 
offload_connect(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen,net_context_connect_cb_t cb,int32_t timeout,void * user_data)1529 static int offload_connect(struct net_context *context,
1530 			   const struct sockaddr *addr,
1531 			   socklen_t addrlen,
1532 			   net_context_connect_cb_t cb,
1533 			   int32_t timeout,
1534 			   void *user_data)
1535 {
1536 	int ret, dst_port = -1;
1537 	int32_t timeout_sec = -1; /* if not changed, this will be min timeout */
1538 	char buf[sizeof("AT@SOCKCONN=#,###.###.###.###,#####,#####\r")];
1539 	struct wncm14a2a_socket *sock;
1540 
1541 	if (timeout > 0) {
1542 		timeout_sec = timeout / MSEC_PER_SEC;
1543 	}
1544 
1545 	if (!context || !addr) {
1546 		return -EINVAL;
1547 	}
1548 
1549 	sock = (struct wncm14a2a_socket *)context->offload_context;
1550 	if (!sock) {
1551 		LOG_ERR("Can't locate socket for net_ctx:%p!", context);
1552 		return -EINVAL;
1553 	}
1554 
1555 	if (sock->socket_id < 1) {
1556 		LOG_ERR("Invalid socket_id(%d) for net_ctx:%p!",
1557 			    sock->socket_id, context);
1558 		return -EINVAL;
1559 	}
1560 
1561 	sock->dst.sa_family = addr->sa_family;
1562 
1563 #if defined(CONFIG_NET_IPV6)
1564 	if (addr->sa_family == AF_INET6) {
1565 		net_ipaddr_copy(&net_sin6(&sock->dst)->sin6_addr,
1566 				&net_sin6(addr)->sin6_addr);
1567 		dst_port = ntohs(net_sin6(addr)->sin6_port);
1568 		net_sin6(&sock->dst)->sin6_port = dst_port;
1569 	} else
1570 #endif
1571 #if defined(CONFIG_NET_IPV4)
1572 	if (addr->sa_family == AF_INET) {
1573 		net_ipaddr_copy(&net_sin(&sock->dst)->sin_addr,
1574 				&net_sin(addr)->sin_addr);
1575 		dst_port = ntohs(net_sin(addr)->sin_port);
1576 		net_sin(&sock->dst)->sin_port = dst_port;
1577 	} else
1578 #endif
1579 	{
1580 		return -EINVAL;
1581 	}
1582 
1583 	if (dst_port < 0) {
1584 		LOG_ERR("Invalid port: %d", dst_port);
1585 		return -EINVAL;
1586 	}
1587 
1588 	/*
1589 	 * AT@SOCKCONN timeout param has minimum value of 30 seconds and
1590 	 * maximum value of 360 seconds, otherwise an error is generated
1591 	 */
1592 	timeout_sec = CLAMP(timeout_sec, 30, 360);
1593 
1594 	snprintk(buf, sizeof(buf), "AT@SOCKCONN=%d,\"%s\",%d,%d",
1595 		 sock->socket_id, wncm14a2a_sprint_ip_addr(addr),
1596 		 dst_port, timeout_sec);
1597 	ret = send_at_cmd(sock, buf, MDM_CMD_CONN_TIMEOUT);
1598 	if (!ret) {
1599 		net_context_set_state(sock->context, NET_CONTEXT_CONNECTED);
1600 	} else {
1601 		LOG_ERR("AT@SOCKCONN ret:%d", ret);
1602 	}
1603 
1604 	if (cb) {
1605 		cb(context, ret, user_data);
1606 	}
1607 
1608 	return ret;
1609 }
1610 
offload_accept(struct net_context * context,net_tcp_accept_cb_t cb,int32_t timeout,void * user_data)1611 static int offload_accept(struct net_context *context,
1612 			  net_tcp_accept_cb_t cb,
1613 			  int32_t timeout,
1614 			  void *user_data)
1615 {
1616 	/* NOT IMPLEMENTED */
1617 	return -ENOTSUP;
1618 }
1619 
offload_sendto(struct net_pkt * pkt,const struct sockaddr * dst_addr,socklen_t addrlen,net_context_send_cb_t cb,int32_t timeout,void * user_data)1620 static int offload_sendto(struct net_pkt *pkt,
1621 			  const struct sockaddr *dst_addr,
1622 			  socklen_t addrlen,
1623 			  net_context_send_cb_t cb,
1624 			  int32_t timeout,
1625 			  void *user_data)
1626 {
1627 	struct net_context *context = net_pkt_context(pkt);
1628 	struct wncm14a2a_socket *sock;
1629 	int ret = 0;
1630 
1631 	if (!context) {
1632 		return -EINVAL;
1633 	}
1634 
1635 	sock = (struct wncm14a2a_socket *)context->offload_context;
1636 	if (!sock) {
1637 		LOG_ERR("Can't locate socket for net_ctx:%p!", context);
1638 		return -EINVAL;
1639 	}
1640 
1641 	ret = send_data(sock, pkt);
1642 	if (ret < 0) {
1643 		LOG_ERR("send_data error: %d", ret);
1644 	} else {
1645 		net_pkt_unref(pkt);
1646 	}
1647 
1648 	if (cb) {
1649 		cb(context, ret, user_data);
1650 	}
1651 
1652 	return ret;
1653 }
1654 
offload_send(struct net_pkt * pkt,net_context_send_cb_t cb,int32_t timeout,void * user_data)1655 static int offload_send(struct net_pkt *pkt,
1656 			net_context_send_cb_t cb,
1657 			int32_t timeout,
1658 			void *user_data)
1659 {
1660 	struct net_context *context = net_pkt_context(pkt);
1661 	socklen_t addrlen;
1662 
1663 #if defined(CONFIG_NET_IPV6)
1664 	if (net_pkt_family(pkt) == AF_INET6) {
1665 		addrlen = sizeof(struct sockaddr_in6);
1666 	} else
1667 #endif /* CONFIG_NET_IPV6 */
1668 #if defined(CONFIG_NET_IPV4)
1669 	if (net_pkt_family(pkt) == AF_INET) {
1670 		addrlen = sizeof(struct sockaddr_in);
1671 	} else
1672 #endif /* CONFIG_NET_IPV4 */
1673 	{
1674 		return -EPFNOSUPPORT;
1675 	}
1676 
1677 	return offload_sendto(pkt, &context->remote, addrlen, cb,
1678 			      timeout, user_data);
1679 }
1680 
offload_recv(struct net_context * context,net_context_recv_cb_t cb,int32_t timeout,void * user_data)1681 static int offload_recv(struct net_context *context,
1682 			net_context_recv_cb_t cb,
1683 			int32_t timeout,
1684 			void *user_data)
1685 {
1686 	struct wncm14a2a_socket *sock;
1687 
1688 	if (!context) {
1689 		return -EINVAL;
1690 	}
1691 
1692 	sock = (struct wncm14a2a_socket *)context->offload_context;
1693 	if (!sock) {
1694 		LOG_ERR("Can't locate socket for net_ctx:%p!", context);
1695 		return -EINVAL;
1696 	}
1697 
1698 	sock->recv_cb = cb;
1699 	sock->recv_user_data = user_data;
1700 
1701 	return 0;
1702 }
1703 
offload_put(struct net_context * context)1704 static int offload_put(struct net_context *context)
1705 {
1706 	struct wncm14a2a_socket *sock;
1707 	char buf[sizeof("AT@SOCKCLOSE=#\r")];
1708 	int ret;
1709 
1710 	if (!context) {
1711 		return -EINVAL;
1712 	}
1713 
1714 	sock = (struct wncm14a2a_socket *)context->offload_context;
1715 	if (!sock) {
1716 		/* socket was already closed?  Exit quietly here. */
1717 		return 0;
1718 	}
1719 
1720 	snprintk(buf, sizeof(buf), "AT@SOCKCLOSE=%d", sock->socket_id);
1721 
1722 	ret = send_at_cmd(sock, buf, MDM_CMD_TIMEOUT);
1723 	if (ret < 0) {
1724 		LOG_ERR("AT@SOCKCLOSE ret:%d", ret);
1725 	}
1726 
1727 	/* clear last_socket_id */
1728 	ictx.last_socket_id = 0;
1729 
1730 	socket_put(sock);
1731 	net_context_unref(context);
1732 	if (sock->type == SOCK_STREAM) {
1733 		/* TCP contexts are referenced twice,
1734 		 *  once for the app and once for the stack.
1735 		 *  Since TCP stack is not used for offload,
1736 		 *  unref a second time.
1737 		 */
1738 		net_context_unref(context);
1739 	}
1740 
1741 	return 0;
1742 }
1743 
1744 static struct net_offload offload_funcs = {
1745 	.get = offload_get,
1746 	.bind = offload_bind,
1747 	.listen = offload_listen,	/* TODO */
1748 	.connect = offload_connect,
1749 	.accept = offload_accept,	/* TODO */
1750 	.send = offload_send,
1751 	.sendto = offload_sendto,
1752 	.recv = offload_recv,
1753 	.put = offload_put,
1754 };
1755 
wncm14a2a_get_mac(const struct device * dev)1756 static inline uint8_t *wncm14a2a_get_mac(const struct device *dev)
1757 {
1758 	struct wncm14a2a_iface_ctx *ctx = dev->data;
1759 
1760 	ctx->mac_addr[0] = 0x00;
1761 	ctx->mac_addr[1] = 0x10;
1762 
1763 	UNALIGNED_PUT(sys_cpu_to_be32(sys_rand32_get()),
1764 		      (uint32_t *)(ctx->mac_addr + 2));
1765 
1766 	return ctx->mac_addr;
1767 }
1768 
offload_iface_init(struct net_if * iface)1769 static void offload_iface_init(struct net_if *iface)
1770 {
1771 	const struct device *dev = net_if_get_device(iface);
1772 	struct wncm14a2a_iface_ctx *ctx = dev->data;
1773 
1774 	iface->if_dev->offload = &offload_funcs;
1775 	net_if_set_link_addr(iface, wncm14a2a_get_mac(dev),
1776 			     sizeof(ctx->mac_addr),
1777 			     NET_LINK_ETHERNET);
1778 	ctx->iface = iface;
1779 }
1780 
1781 static struct offloaded_if_api api_funcs = {
1782 	.iface_api.init = offload_iface_init,
1783 };
1784 
1785 NET_DEVICE_DT_INST_OFFLOAD_DEFINE(0, wncm14a2a_init, NULL,
1786 				  &ictx, &wncm14a2a_cfg,
1787 				  CONFIG_MODEM_WNCM14A2A_INIT_PRIORITY,
1788 				  &api_funcs,
1789 				  MDM_MAX_DATA_LENGTH);
1790