1 /*
2  * Copyright (c) 2020 Analog Life LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT quectel_bg9x
8 
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(modem_quectel_bg9x, CONFIG_MODEM_LOG_LEVEL);
11 
12 #include "quectel-bg9x.h"
13 
14 static struct k_thread	       modem_rx_thread;
15 static struct k_work_q	       modem_workq;
16 static struct modem_data       mdata;
17 static struct modem_context    mctx;
18 static const struct socket_op_vtable offload_socket_fd_op_vtable;
19 
20 static K_KERNEL_STACK_DEFINE(modem_rx_stack, CONFIG_MODEM_QUECTEL_BG9X_RX_STACK_SIZE);
21 static K_KERNEL_STACK_DEFINE(modem_workq_stack, CONFIG_MODEM_QUECTEL_BG9X_RX_WORKQ_STACK_SIZE);
22 NET_BUF_POOL_DEFINE(mdm_recv_pool, MDM_RECV_MAX_BUF, MDM_RECV_BUF_SIZE, 0, NULL);
23 
24 static const struct gpio_dt_spec power_gpio = GPIO_DT_SPEC_INST_GET(0, mdm_power_gpios);
25 #if DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
26 static const struct gpio_dt_spec reset_gpio = GPIO_DT_SPEC_INST_GET(0, mdm_reset_gpios);
27 #endif
28 #if DT_INST_NODE_HAS_PROP(0, mdm_dtr_gpios)
29 static const struct gpio_dt_spec dtr_gpio = GPIO_DT_SPEC_INST_GET(0, mdm_dtr_gpios);
30 #endif
31 #if DT_INST_NODE_HAS_PROP(0, mdm_wdisable_gpios)
32 static const struct gpio_dt_spec wdisable_gpio = GPIO_DT_SPEC_INST_GET(0, mdm_wdisable_gpios);
33 #endif
34 
digits(int n)35 static inline int digits(int n)
36 {
37 	int count = 0;
38 
39 	while (n != 0) {
40 		n /= 10;
41 		++count;
42 	}
43 
44 	return count;
45 }
46 
hash32(char * str,int len)47 static inline uint32_t hash32(char *str, int len)
48 {
49 #define HASH_MULTIPLIER		37
50 
51 	uint32_t h = 0;
52 	int i;
53 
54 	for (i = 0; i < len; ++i) {
55 		h = (h * HASH_MULTIPLIER) + str[i];
56 	}
57 
58 	return h;
59 }
60 
modem_get_mac(const struct device * dev)61 static inline uint8_t *modem_get_mac(const struct device *dev)
62 {
63 	struct modem_data *data = dev->data;
64 	uint32_t hash_value;
65 
66 	data->mac_addr[0] = 0x00;
67 	data->mac_addr[1] = 0x10;
68 
69 	/* use IMEI for mac_addr */
70 	hash_value = hash32(mdata.mdm_imei, strlen(mdata.mdm_imei));
71 
72 	UNALIGNED_PUT(hash_value, (uint32_t *)(data->mac_addr + 2));
73 
74 	return data->mac_addr;
75 }
76 
77 /* Func: modem_atoi
78  * Desc: Convert string to long integer, but handle errors
79  */
modem_atoi(const char * s,const int err_value,const char * desc,const char * func)80 static int modem_atoi(const char *s, const int err_value,
81 		      const char *desc, const char *func)
82 {
83 	int   ret;
84 	char  *endptr;
85 
86 	ret = (int)strtol(s, &endptr, 10);
87 	if (!endptr || *endptr != '\0') {
88 		LOG_ERR("bad %s '%s' in %s", s, desc,
89 			func);
90 		return err_value;
91 	}
92 
93 	return ret;
94 }
95 
find_len(char * data)96 static inline int find_len(char *data)
97 {
98 	char buf[10] = {0};
99 	int  i;
100 
101 	for (i = 0; i < 10; i++) {
102 		if (data[i] == '\r') {
103 			break;
104 		}
105 
106 		buf[i] = data[i];
107 	}
108 
109 	return ATOI(buf, 0, "rx_buf");
110 }
111 
112 /* Func: on_cmd_sockread_common
113  * Desc: Function to successfully read data from the modem on a given socket.
114  */
on_cmd_sockread_common(int socket_fd,struct modem_cmd_handler_data * data,uint16_t len)115 static int on_cmd_sockread_common(int socket_fd,
116 				  struct modem_cmd_handler_data *data,
117 				  uint16_t len)
118 {
119 	struct modem_socket	 *sock = NULL;
120 	struct socket_read_data	 *sock_data;
121 	int ret, i;
122 	int socket_data_length;
123 	int bytes_to_skip;
124 
125 	if (!len) {
126 		LOG_ERR("Invalid length, Aborting!");
127 		return -EAGAIN;
128 	}
129 
130 	/* Make sure we still have buf data */
131 	if (!data->rx_buf) {
132 		LOG_ERR("Incorrect format! Ignoring data!");
133 		return -EINVAL;
134 	}
135 
136 	socket_data_length = find_len(data->rx_buf->data);
137 
138 	/* No (or not enough) data available on the socket. */
139 	bytes_to_skip = digits(socket_data_length) + 2 + 4;
140 	if (socket_data_length <= 0) {
141 		LOG_ERR("Length problem (%d).  Aborting!", socket_data_length);
142 		return -EAGAIN;
143 	}
144 
145 	/* check to make sure we have all of the data. */
146 	if (net_buf_frags_len(data->rx_buf) < (socket_data_length + bytes_to_skip)) {
147 		LOG_DBG("Not enough data -- wait!");
148 		return -EAGAIN;
149 	}
150 
151 	/* Skip "len" and CRLF */
152 	bytes_to_skip = digits(socket_data_length) + 2;
153 	for (i = 0; i < bytes_to_skip; i++) {
154 		net_buf_pull_u8(data->rx_buf);
155 	}
156 
157 	if (!data->rx_buf->len) {
158 		data->rx_buf = net_buf_frag_del(NULL, data->rx_buf);
159 	}
160 
161 	sock = modem_socket_from_fd(&mdata.socket_config, socket_fd);
162 	if (!sock) {
163 		LOG_ERR("Socket not found! (%d)", socket_fd);
164 		ret = -EINVAL;
165 		goto exit;
166 	}
167 
168 	sock_data = (struct socket_read_data *)sock->data;
169 	if (!sock_data) {
170 		LOG_ERR("Socket data not found! Skip handling (%d)", socket_fd);
171 		ret = -EINVAL;
172 		goto exit;
173 	}
174 
175 	ret = net_buf_linearize(sock_data->recv_buf, sock_data->recv_buf_len,
176 				data->rx_buf, 0, (uint16_t)socket_data_length);
177 	data->rx_buf = net_buf_skip(data->rx_buf, ret);
178 	sock_data->recv_read_len = ret;
179 	if (ret != socket_data_length) {
180 		LOG_ERR("Total copied data is different then received data!"
181 			" copied:%d vs. received:%d", ret, socket_data_length);
182 		ret = -EINVAL;
183 	}
184 
185 exit:
186 	/* remove packet from list (ignore errors) */
187 	(void)modem_socket_packet_size_update(&mdata.socket_config, sock,
188 					      -socket_data_length);
189 
190 	/* don't give back semaphore -- OK to follow */
191 	return ret;
192 }
193 
194 /* Func: socket_close
195  * Desc: Function to close the given socket descriptor.
196  */
socket_close(struct modem_socket * sock)197 static void socket_close(struct modem_socket *sock)
198 {
199 	char buf[sizeof("AT+QICLOSE=##")] = {0};
200 	int  ret;
201 
202 	snprintk(buf, sizeof(buf), "AT+QICLOSE=%d", sock->id);
203 
204 	/* Tell the modem to close the socket. */
205 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
206 			     NULL, 0U, buf,
207 			     &mdata.sem_response, MDM_CMD_TIMEOUT);
208 	if (ret < 0) {
209 		LOG_ERR("%s ret:%d", buf, ret);
210 	}
211 
212 	modem_socket_put(&mdata.socket_config, sock->sock_fd);
213 }
214 
215 /* Handler: OK */
MODEM_CMD_DEFINE(on_cmd_ok)216 MODEM_CMD_DEFINE(on_cmd_ok)
217 {
218 	modem_cmd_handler_set_error(data, 0);
219 	k_sem_give(&mdata.sem_response);
220 	return 0;
221 }
222 
223 /* Handler: ERROR */
MODEM_CMD_DEFINE(on_cmd_error)224 MODEM_CMD_DEFINE(on_cmd_error)
225 {
226 	modem_cmd_handler_set_error(data, -EIO);
227 	k_sem_give(&mdata.sem_response);
228 	return 0;
229 }
230 
231 /* Handler: +CME Error: <err>[0] */
MODEM_CMD_DEFINE(on_cmd_exterror)232 MODEM_CMD_DEFINE(on_cmd_exterror)
233 {
234 	modem_cmd_handler_set_error(data, -EIO);
235 	k_sem_give(&mdata.sem_response);
236 	return 0;
237 }
238 
239 /* Handler: +CSQ: <signal_power>[0], <qual>[1] */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_csq)240 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_csq)
241 {
242 	int rssi = ATOI(argv[0], 0, "signal_power");
243 
244 	/* Check the RSSI value. */
245 	if (rssi == 31) {
246 		mdata.mdm_rssi = -51;
247 	} else if (rssi >= 0 && rssi <= 31) {
248 		mdata.mdm_rssi = -114 + ((rssi * 2) + 1);
249 	} else {
250 		mdata.mdm_rssi = -1000;
251 	}
252 
253 	LOG_INF("RSSI: %d", mdata.mdm_rssi);
254 	return 0;
255 }
256 
257 /* Handler: +QIOPEN: <connect_id>[0], <err>[1] */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_sockopen)258 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_sockopen)
259 {
260 	int err = ATOI(argv[1], 0, "sock_err");
261 
262 	LOG_INF("AT+QIOPEN: %d", err);
263 	modem_cmd_handler_set_error(data, err);
264 	k_sem_give(&mdata.sem_sock_conn);
265 
266 	return 0;
267 }
268 
269 /* Handler: <manufacturer> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_manufacturer)270 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_manufacturer)
271 {
272 	size_t out_len = net_buf_linearize(mdata.mdm_manufacturer,
273 					   sizeof(mdata.mdm_manufacturer) - 1,
274 					   data->rx_buf, 0, len);
275 	mdata.mdm_manufacturer[out_len] = '\0';
276 	LOG_INF("Manufacturer: %s", mdata.mdm_manufacturer);
277 	return 0;
278 }
279 
280 /* Handler: <model> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_model)281 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_model)
282 {
283 	size_t out_len = net_buf_linearize(mdata.mdm_model,
284 					   sizeof(mdata.mdm_model) - 1,
285 					   data->rx_buf, 0, len);
286 	mdata.mdm_model[out_len] = '\0';
287 
288 	/* Log the received information. */
289 	LOG_INF("Model: %s", mdata.mdm_model);
290 	return 0;
291 }
292 
293 /* Handler: <rev> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_revision)294 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_revision)
295 {
296 	size_t out_len = net_buf_linearize(mdata.mdm_revision,
297 					   sizeof(mdata.mdm_revision) - 1,
298 					   data->rx_buf, 0, len);
299 	mdata.mdm_revision[out_len] = '\0';
300 
301 	/* Log the received information. */
302 	LOG_INF("Revision: %s", mdata.mdm_revision);
303 	return 0;
304 }
305 
306 /* Handler: <IMEI> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imei)307 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imei)
308 {
309 	size_t out_len = net_buf_linearize(mdata.mdm_imei,
310 					   sizeof(mdata.mdm_imei) - 1,
311 					   data->rx_buf, 0, len);
312 	mdata.mdm_imei[out_len] = '\0';
313 
314 	/* Log the received information. */
315 	LOG_INF("IMEI: %s", mdata.mdm_imei);
316 	return 0;
317 }
318 
319 #if defined(CONFIG_MODEM_SIM_NUMBERS)
320 /* Handler: <IMSI> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imsi)321 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imsi)
322 {
323 	size_t	out_len = net_buf_linearize(mdata.mdm_imsi,
324 					    sizeof(mdata.mdm_imsi) - 1,
325 					    data->rx_buf, 0, len);
326 	mdata.mdm_imsi[out_len] = '\0';
327 
328 	/* Log the received information. */
329 	LOG_INF("IMSI: %s", mdata.mdm_imsi);
330 	return 0;
331 }
332 
333 /* Handler: <ICCID> */
MODEM_CMD_DEFINE(on_cmd_atcmdinfo_iccid)334 MODEM_CMD_DEFINE(on_cmd_atcmdinfo_iccid)
335 {
336 	size_t out_len;
337 	char   *p;
338 
339 	out_len = net_buf_linearize(mdata.mdm_iccid, sizeof(mdata.mdm_iccid) - 1,
340 				    data->rx_buf, 0, len);
341 	mdata.mdm_iccid[out_len] = '\0';
342 
343 	/* Skip over the +CCID bit, which modems omit. */
344 	if (mdata.mdm_iccid[0] == '+') {
345 		p = strchr(mdata.mdm_iccid, ' ');
346 		if (p) {
347 			out_len = strlen(p + 1);
348 			memmove(mdata.mdm_iccid, p + 1, len + 1);
349 		}
350 	}
351 
352 	LOG_INF("ICCID: %s", mdata.mdm_iccid);
353 	return 0;
354 }
355 #endif /* #if defined(CONFIG_MODEM_SIM_NUMBERS) */
356 
357 /* Handler: TX Ready */
MODEM_CMD_DIRECT_DEFINE(on_cmd_tx_ready)358 MODEM_CMD_DIRECT_DEFINE(on_cmd_tx_ready)
359 {
360 	k_sem_give(&mdata.sem_tx_ready);
361 	return len;
362 }
363 
364 /* Handler: SEND OK */
MODEM_CMD_DEFINE(on_cmd_send_ok)365 MODEM_CMD_DEFINE(on_cmd_send_ok)
366 {
367 	modem_cmd_handler_set_error(data, 0);
368 	k_sem_give(&mdata.sem_response);
369 
370 	return 0;
371 }
372 
373 /* Handler: SEND FAIL */
MODEM_CMD_DEFINE(on_cmd_send_fail)374 MODEM_CMD_DEFINE(on_cmd_send_fail)
375 {
376 	mdata.sock_written = 0;
377 	modem_cmd_handler_set_error(data, -EIO);
378 	k_sem_give(&mdata.sem_response);
379 
380 	return 0;
381 }
382 
383 /* Handler: Read data */
MODEM_CMD_DEFINE(on_cmd_sock_readdata)384 MODEM_CMD_DEFINE(on_cmd_sock_readdata)
385 {
386 	return on_cmd_sockread_common(mdata.sock_fd, data, len);
387 }
388 
389 /* Handler: Data receive indication. */
MODEM_CMD_DEFINE(on_cmd_unsol_recv)390 MODEM_CMD_DEFINE(on_cmd_unsol_recv)
391 {
392 	struct modem_socket *sock;
393 	int		     sock_fd;
394 
395 	sock_fd = ATOI(argv[0], 0, "sock_fd");
396 
397 	/* Socket pointer from FD. */
398 	sock = modem_socket_from_fd(&mdata.socket_config, sock_fd);
399 	if (!sock) {
400 		return 0;
401 	}
402 
403 	/* Data ready indication. */
404 	LOG_INF("Data Receive Indication for socket: %d", sock_fd);
405 	modem_socket_data_ready(&mdata.socket_config, sock);
406 
407 	return 0;
408 }
409 
410 /* Handler: Socket Close Indication. */
MODEM_CMD_DEFINE(on_cmd_unsol_close)411 MODEM_CMD_DEFINE(on_cmd_unsol_close)
412 {
413 	struct modem_socket *sock;
414 	int		     sock_fd;
415 
416 	sock_fd = ATOI(argv[0], 0, "sock_fd");
417 	sock	= modem_socket_from_fd(&mdata.socket_config, sock_fd);
418 	if (!sock) {
419 		return 0;
420 	}
421 
422 	LOG_INF("Socket Close Indication for socket: %d", sock_fd);
423 
424 	/* Tell the modem to close the socket. */
425 	socket_close(sock);
426 	LOG_INF("Socket Closed: %d", sock_fd);
427 	return 0;
428 }
429 
430 /* Handler: Modem initialization ready. */
MODEM_CMD_DEFINE(on_cmd_unsol_rdy)431 MODEM_CMD_DEFINE(on_cmd_unsol_rdy)
432 {
433 	k_sem_give(&mdata.sem_response);
434 	return 0;
435 }
436 
437 /* Func: send_socket_data
438  * Desc: This function will send "binary" data over the socket object.
439  */
send_socket_data(struct modem_socket * sock,const struct sockaddr * dst_addr,struct modem_cmd * handler_cmds,size_t handler_cmds_len,const char * buf,size_t buf_len,k_timeout_t timeout)440 static ssize_t send_socket_data(struct modem_socket *sock,
441 				const struct sockaddr *dst_addr,
442 				struct modem_cmd *handler_cmds,
443 				size_t handler_cmds_len,
444 				const char *buf, size_t buf_len,
445 				k_timeout_t timeout)
446 {
447 	int  ret;
448 	char send_buf[sizeof("AT+QISEND=##,####")] = {0};
449 	char ctrlz = 0x1A;
450 
451 	if (buf_len > MDM_MAX_DATA_LENGTH) {
452 		buf_len = MDM_MAX_DATA_LENGTH;
453 	}
454 
455 	/* Create a buffer with the correct params. */
456 	mdata.sock_written = buf_len;
457 	snprintk(send_buf, sizeof(send_buf), "AT+QISEND=%d,%ld", sock->id, (long) buf_len);
458 
459 	/* Setup the locks correctly. */
460 	(void)k_sem_take(&mdata.cmd_handler_data.sem_tx_lock, K_FOREVER);
461 	k_sem_reset(&mdata.sem_tx_ready);
462 
463 	/* Send the Modem command. */
464 	ret = modem_cmd_send_nolock(&mctx.iface, &mctx.cmd_handler,
465 				    NULL, 0U, send_buf, NULL, K_NO_WAIT);
466 	if (ret < 0) {
467 		goto exit;
468 	}
469 
470 	/* set command handlers */
471 	ret = modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
472 					    handler_cmds, handler_cmds_len,
473 					    true);
474 	if (ret < 0) {
475 		goto exit;
476 	}
477 
478 	/* Wait for '>' */
479 	ret = k_sem_take(&mdata.sem_tx_ready, K_MSEC(5000));
480 	if (ret < 0) {
481 		/* Didn't get the data prompt - Exit. */
482 		LOG_DBG("Timeout waiting for tx");
483 		goto exit;
484 	}
485 
486 	/* Write all data on the console and send CTRL+Z. */
487 	mctx.iface.write(&mctx.iface, buf, buf_len);
488 	mctx.iface.write(&mctx.iface, &ctrlz, 1);
489 
490 	/* Wait for 'SEND OK' or 'SEND FAIL' */
491 	k_sem_reset(&mdata.sem_response);
492 	ret = k_sem_take(&mdata.sem_response, timeout);
493 	if (ret < 0) {
494 		LOG_DBG("No send response");
495 		goto exit;
496 	}
497 
498 	ret = modem_cmd_handler_get_error(&mdata.cmd_handler_data);
499 	if (ret != 0) {
500 		LOG_DBG("Failed to send data");
501 	}
502 
503 exit:
504 	/* unset handler commands and ignore any errors */
505 	(void)modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
506 					    NULL, 0U, false);
507 	k_sem_give(&mdata.cmd_handler_data.sem_tx_lock);
508 
509 	if (ret < 0) {
510 		return ret;
511 	}
512 
513 	/* Return the amount of data written on the socket. */
514 	return mdata.sock_written;
515 }
516 
517 /* Func: offload_sendto
518  * Desc: This function will send data on the socket object.
519  */
offload_sendto(void * obj,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)520 static ssize_t offload_sendto(void *obj, const void *buf, size_t len,
521 			      int flags, const struct sockaddr *to,
522 			      socklen_t tolen)
523 {
524 	int ret;
525 	struct modem_socket *sock = (struct modem_socket *) obj;
526 
527 	/* Here's how sending data works,
528 	 * -> We firstly send the "AT+QISEND" command on the given socket and
529 	 *    specify the length of data to be transferred.
530 	 * -> In response to "AT+QISEND" command, the modem may respond with a
531 	 *    data prompt (>) or not respond at all. If it doesn't respond, we
532 	 *    exit. If it does respond with a data prompt (>), we move forward.
533 	 * -> We plainly write all data on the UART and terminate by sending a
534 	 *    CTRL+Z. Once the modem receives CTRL+Z, it starts processing the
535 	 *    data and will respond with either "SEND OK", "SEND FAIL" or "ERROR".
536 	 *    Here we are registering handlers for the first two responses. We
537 	 *    already have a handler for the "generic" error response.
538 	 */
539 	struct modem_cmd cmd[] = {
540 		MODEM_CMD_DIRECT(">", on_cmd_tx_ready),
541 		MODEM_CMD("SEND OK", on_cmd_send_ok,   0, ","),
542 		MODEM_CMD("SEND FAIL", on_cmd_send_fail, 0, ","),
543 	};
544 
545 	/* Ensure that valid parameters are passed. */
546 	if (!buf || len == 0) {
547 		errno = EINVAL;
548 		return -1;
549 	}
550 
551 	/* UDP is not supported. */
552 	if (sock->ip_proto == IPPROTO_UDP) {
553 		errno = ENOTSUP;
554 		return -1;
555 	}
556 
557 	if (!sock->is_connected) {
558 		errno = ENOTCONN;
559 		return -1;
560 	}
561 
562 	ret = send_socket_data(sock, to, cmd, ARRAY_SIZE(cmd), buf, len,
563 			       MDM_CMD_TIMEOUT);
564 	if (ret < 0) {
565 		errno = -ret;
566 		return -1;
567 	}
568 
569 	/* Data was written successfully. */
570 	errno = 0;
571 	return ret;
572 }
573 
574 /* Func: offload_recvfrom
575  * Desc: This function will receive data on the socket object.
576  */
offload_recvfrom(void * obj,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)577 static ssize_t offload_recvfrom(void *obj, void *buf, size_t len,
578 				int flags, struct sockaddr *from,
579 				socklen_t *fromlen)
580 {
581 	struct modem_socket *sock = (struct modem_socket *)obj;
582 	char   sendbuf[sizeof("AT+QIRD=##,####")] = {0};
583 	int    ret;
584 	struct socket_read_data sock_data;
585 
586 	/* Modem command to read the data. */
587 	struct modem_cmd data_cmd[] = { MODEM_CMD("+QIRD: ", on_cmd_sock_readdata, 0U, "") };
588 
589 	if (!buf || len == 0) {
590 		errno = EINVAL;
591 		return -1;
592 	}
593 
594 	if (flags & ZSOCK_MSG_PEEK) {
595 		errno = ENOTSUP;
596 		return -1;
597 	}
598 
599 	snprintk(sendbuf, sizeof(sendbuf), "AT+QIRD=%d,%zd", sock->id, len);
600 
601 	/* Socket read settings */
602 	(void) memset(&sock_data, 0, sizeof(sock_data));
603 	sock_data.recv_buf     = buf;
604 	sock_data.recv_buf_len = len;
605 	sock_data.recv_addr    = from;
606 	sock->data	       = &sock_data;
607 	mdata.sock_fd	       = sock->sock_fd;
608 
609 	/* Tell the modem to give us data (AT+QIRD=id,data_len). */
610 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
611 			     data_cmd, ARRAY_SIZE(data_cmd), sendbuf, &mdata.sem_response,
612 			     MDM_CMD_TIMEOUT);
613 	if (ret < 0) {
614 		errno = -ret;
615 		ret = -1;
616 		goto exit;
617 	}
618 
619 	/* HACK: use dst address as from */
620 	if (from && fromlen) {
621 		*fromlen = sizeof(sock->dst);
622 		memcpy(from, &sock->dst, *fromlen);
623 	}
624 
625 	/* return length of received data */
626 	errno = 0;
627 	ret = sock_data.recv_read_len;
628 
629 exit:
630 	/* clear socket data */
631 	sock->data = NULL;
632 	return ret;
633 }
634 
635 /* Func: offload_read
636  * Desc: This function reads data from the given socket object.
637  */
offload_read(void * obj,void * buffer,size_t count)638 static ssize_t offload_read(void *obj, void *buffer, size_t count)
639 {
640 	return offload_recvfrom(obj, buffer, count, 0, NULL, 0);
641 }
642 
643 /* Func: offload_write
644  * Desc: This function writes data to the given socket object.
645  */
offload_write(void * obj,const void * buffer,size_t count)646 static ssize_t offload_write(void *obj, const void *buffer, size_t count)
647 {
648 	return offload_sendto(obj, buffer, count, 0, NULL, 0);
649 }
650 
651 /* Func: offload_ioctl
652  * Desc: Function call to handle various misc requests.
653  */
offload_ioctl(void * obj,unsigned int request,va_list args)654 static int offload_ioctl(void *obj, unsigned int request, va_list args)
655 {
656 	switch (request) {
657 	case ZFD_IOCTL_POLL_PREPARE: {
658 		struct zsock_pollfd *pfd;
659 		struct k_poll_event **pev;
660 		struct k_poll_event *pev_end;
661 
662 		pfd = va_arg(args, struct zsock_pollfd *);
663 		pev = va_arg(args, struct k_poll_event **);
664 		pev_end = va_arg(args, struct k_poll_event *);
665 
666 		return modem_socket_poll_prepare(&mdata.socket_config, obj, pfd, pev, pev_end);
667 	}
668 	case ZFD_IOCTL_POLL_UPDATE: {
669 		struct zsock_pollfd *pfd;
670 		struct k_poll_event **pev;
671 
672 		pfd = va_arg(args, struct zsock_pollfd *);
673 		pev = va_arg(args, struct k_poll_event **);
674 
675 		return modem_socket_poll_update(obj, pfd, pev);
676 	}
677 
678 	default:
679 		errno = EINVAL;
680 		return -1;
681 	}
682 }
683 
684 /* Func: offload_connect
685  * Desc: This function will connect with a provided TCP.
686  */
offload_connect(void * obj,const struct sockaddr * addr,socklen_t addrlen)687 static int offload_connect(void *obj, const struct sockaddr *addr,
688 						   socklen_t addrlen)
689 {
690 	struct modem_socket *sock     = (struct modem_socket *) obj;
691 	uint16_t	    dst_port  = 0;
692 	char		    *protocol = "TCP";
693 	struct modem_cmd    cmd[]     = { MODEM_CMD("+QIOPEN: ", on_cmd_atcmdinfo_sockopen, 2U, ",") };
694 	char		    buf[sizeof("AT+QIOPEN=#,#,'###','###',"
695 				       "####.####.####.####.####.####.####.####,######,"
696 				       "0,0")] = {0};
697 	int		    ret;
698 	char		    ip_str[NET_IPV6_ADDR_LEN];
699 
700 	/* Verify socket has been allocated */
701 	if (modem_socket_is_allocated(&mdata.socket_config, sock) == false) {
702 		LOG_ERR("Invalid socket_id(%d) from fd:%d",
703 			sock->id, sock->sock_fd);
704 		errno = EINVAL;
705 		return -1;
706 	}
707 
708 	if (sock->is_connected == true) {
709 		LOG_ERR("Socket is already connected!! socket_id(%d), socket_fd:%d",
710 			sock->id, sock->sock_fd);
711 		errno = EISCONN;
712 		return -1;
713 	}
714 
715 	/* Find the correct destination port. */
716 	if (addr->sa_family == AF_INET6) {
717 		dst_port = ntohs(net_sin6(addr)->sin6_port);
718 	} else if (addr->sa_family == AF_INET) {
719 		dst_port = ntohs(net_sin(addr)->sin_port);
720 	}
721 
722 	/* UDP is not supported. */
723 	if (sock->ip_proto == IPPROTO_UDP) {
724 		errno = ENOTSUP;
725 		return -1;
726 	}
727 
728 	k_sem_reset(&mdata.sem_sock_conn);
729 
730 	ret = modem_context_sprint_ip_addr(addr, ip_str, sizeof(ip_str));
731 	if (ret != 0) {
732 		LOG_ERR("Error formatting IP string %d", ret);
733 		LOG_ERR("Closing the socket!!!");
734 		socket_close(sock);
735 		errno = -ret;
736 		return -1;
737 	}
738 
739 	/* Formulate the complete string. */
740 	snprintk(buf, sizeof(buf), "AT+QIOPEN=%d,%d,\"%s\",\"%s\",%d,0,0", 1, sock->id, protocol,
741 		 ip_str, dst_port);
742 
743 	/* Send out the command. */
744 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
745 			     NULL, 0U, buf,
746 			     &mdata.sem_response, K_SECONDS(1));
747 	if (ret < 0) {
748 		LOG_ERR("%s ret:%d", buf, ret);
749 		LOG_ERR("Closing the socket!!!");
750 		socket_close(sock);
751 		errno = -ret;
752 		return -1;
753 	}
754 
755 	/* set command handlers */
756 	ret = modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
757 					    cmd, ARRAY_SIZE(cmd), true);
758 	if (ret < 0) {
759 		goto exit;
760 	}
761 
762 	/* Wait for QI+OPEN */
763 	ret = k_sem_take(&mdata.sem_sock_conn, MDM_CMD_CONN_TIMEOUT);
764 	if (ret < 0) {
765 		LOG_ERR("Timeout waiting for socket open");
766 		LOG_ERR("Closing the socket!!!");
767 		socket_close(sock);
768 		goto exit;
769 	}
770 
771 	ret = modem_cmd_handler_get_error(&mdata.cmd_handler_data);
772 	if (ret != 0) {
773 		LOG_ERR("Closing the socket!!!");
774 		socket_close(sock);
775 		goto exit;
776 	}
777 
778 	/* Connected successfully. */
779 	sock->is_connected = true;
780 	errno = 0;
781 	return 0;
782 
783 exit:
784 	(void) modem_cmd_handler_update_cmds(&mdata.cmd_handler_data,
785 					     NULL, 0U, false);
786 	errno = -ret;
787 	return -1;
788 }
789 
790 /* Func: offload_close
791  * Desc: This function closes the connection with the remote client and
792  * frees the socket.
793  */
offload_close(void * obj)794 static int offload_close(void *obj)
795 {
796 	struct modem_socket *sock = (struct modem_socket *) obj;
797 
798 	/* Make sure socket is allocated */
799 	if (modem_socket_is_allocated(&mdata.socket_config, sock) == false) {
800 		return 0;
801 	}
802 
803 	/* Close the socket only if it is connected. */
804 	if (sock->is_connected) {
805 		socket_close(sock);
806 	}
807 
808 	return 0;
809 }
810 
811 /* Func: offload_sendmsg
812  * Desc: This function sends messages to the modem.
813  */
offload_sendmsg(void * obj,const struct msghdr * msg,int flags)814 static ssize_t offload_sendmsg(void *obj, const struct msghdr *msg, int flags)
815 {
816 	ssize_t sent = 0;
817 	int rc;
818 
819 	LOG_DBG("msg_iovlen:%zd flags:%d", msg->msg_iovlen, flags);
820 
821 	for (int i = 0; i < msg->msg_iovlen; i++) {
822 		const char *buf = msg->msg_iov[i].iov_base;
823 		size_t len	= msg->msg_iov[i].iov_len;
824 
825 		while (len > 0) {
826 			rc = offload_sendto(obj, buf, len, flags,
827 					    msg->msg_name, msg->msg_namelen);
828 			if (rc < 0) {
829 				if (rc == -EAGAIN) {
830 					k_sleep(MDM_SENDMSG_SLEEP);
831 				} else {
832 					sent = rc;
833 					break;
834 				}
835 			} else {
836 				sent += rc;
837 				buf += rc;
838 				len -= rc;
839 			}
840 		}
841 	}
842 
843 	return (ssize_t) sent;
844 }
845 
846 /* Func: modem_rx
847  * Desc: Thread to process all messages received from the Modem.
848  */
modem_rx(void * p1,void * p2,void * p3)849 static void modem_rx(void *p1, void *p2, void *p3)
850 {
851 	ARG_UNUSED(p1);
852 	ARG_UNUSED(p2);
853 	ARG_UNUSED(p3);
854 
855 	while (true) {
856 
857 		/* Wait for incoming data */
858 		modem_iface_uart_rx_wait(&mctx.iface, K_FOREVER);
859 
860 		modem_cmd_handler_process(&mctx.cmd_handler, &mctx.iface);
861 	}
862 }
863 
864 /* Func: modem_rssi_query_work
865  * Desc: Routine to get Modem RSSI.
866  */
modem_rssi_query_work(struct k_work * work)867 static void modem_rssi_query_work(struct k_work *work)
868 {
869 	struct modem_cmd cmd  = MODEM_CMD("+CSQ: ", on_cmd_atcmdinfo_rssi_csq, 2U, ",");
870 	static char *send_cmd = "AT+CSQ";
871 	int ret;
872 
873 	/* query modem RSSI */
874 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
875 			     &cmd, 1U, send_cmd, &mdata.sem_response,
876 			     MDM_CMD_TIMEOUT);
877 	if (ret < 0) {
878 		LOG_ERR("AT+CSQ ret:%d", ret);
879 	}
880 
881 	/* Re-start RSSI query work */
882 	if (work) {
883 		k_work_reschedule_for_queue(&modem_workq,
884 					    &mdata.rssi_query_work,
885 					    K_SECONDS(RSSI_TIMEOUT_SECS));
886 	}
887 }
888 
889 /* Func: pin_init
890  * Desc: Boot up the Modem.
891  */
pin_init(void)892 static void pin_init(void)
893 {
894 #if !DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
895 	int ret = k_sem_take(&mdata.sem_pin_busy, K_SECONDS(3));
896 
897 	if (ret < 0) {
898 		LOG_DBG("Timeout pin_init()");
899 	}
900 #endif /* !DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios) */
901 	LOG_INF("Setting Modem Pins");
902 
903 #if DT_INST_NODE_HAS_PROP(0, mdm_wdisable_gpios)
904 	LOG_INF("Deactivate W Disable");
905 	gpio_pin_set_dt(&wdisable_gpio, 0);
906 	k_sleep(K_MSEC(250));
907 #endif
908 
909 	/* NOTE: Per the BG95 document, the Reset pin is internally connected to the
910 	 * Power key pin.
911 	 */
912 
913 	/* MDM_POWER -> 1 for 500-1000 msec. */
914 	gpio_pin_set_dt(&power_gpio, 1);
915 	k_sleep(K_MSEC(750));
916 
917 	/* MDM_POWER -> 0 and wait for ~2secs as UART remains in "inactive" state
918 	 * for some time after the power signal is enabled.
919 	 */
920 	gpio_pin_set_dt(&power_gpio, 0);
921 	k_sleep(K_SECONDS(2));
922 
923 	LOG_INF("... Done!");
924 
925 #if !DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
926 	k_sem_give(&mdata.sem_pin_busy);
927 #endif /* !DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios) */
928 }
929 
MODEM_CMD_DEFINE(on_cmd_unsol_normal_power_down)930 MODEM_CMD_DEFINE(on_cmd_unsol_normal_power_down)
931 {
932 	LOG_INF("Modem powering off. Re-power modem...");
933 	pin_init();
934 
935 	return 0;
936 }
937 
938 static const struct modem_cmd response_cmds[] = {
939 	MODEM_CMD("OK", on_cmd_ok, 0U, ""),
940 	MODEM_CMD("ERROR", on_cmd_error, 0U, ""),
941 	MODEM_CMD("+CME ERROR: ", on_cmd_exterror, 1U, ""),
942 };
943 
944 static const struct modem_cmd unsol_cmds[] = {
945 	MODEM_CMD("+QIURC: \"recv\",",	   on_cmd_unsol_recv,  1U, ""),
946 	MODEM_CMD("+QIURC: \"closed\",",   on_cmd_unsol_close, 1U, ""),
947 	MODEM_CMD(MDM_UNSOL_RDY, on_cmd_unsol_rdy, 0U, ""),
948 	MODEM_CMD("NORMAL POWER DOWN", on_cmd_unsol_normal_power_down, 0U, ""),
949 };
950 
951 /* Commands sent to the modem to set it up at boot time. */
952 static const struct setup_cmd setup_cmds[] = {
953 	SETUP_CMD_NOHANDLE("ATE0"),
954 	SETUP_CMD_NOHANDLE("ATH"),
955 	SETUP_CMD_NOHANDLE("AT+CMEE=1"),
956 
957 	/* Commands to read info from the modem (things like IMEI, Model etc). */
958 	SETUP_CMD("AT+CGMI", "", on_cmd_atcmdinfo_manufacturer, 0U, ""),
959 	SETUP_CMD("AT+CGMM", "", on_cmd_atcmdinfo_model, 0U, ""),
960 	SETUP_CMD("AT+CGMR", "", on_cmd_atcmdinfo_revision, 0U, ""),
961 	SETUP_CMD("AT+CGSN", "", on_cmd_atcmdinfo_imei, 0U, ""),
962 #if defined(CONFIG_MODEM_SIM_NUMBERS)
963 	SETUP_CMD("AT+CIMI", "", on_cmd_atcmdinfo_imsi, 0U, ""),
964 	SETUP_CMD("AT+QCCID", "", on_cmd_atcmdinfo_iccid, 0U, ""),
965 #endif /* #if defined(CONFIG_MODEM_SIM_NUMBERS) */
966 	SETUP_CMD_NOHANDLE("AT+QICSGP=1,1,\"" MDM_APN "\",\""
967 			   MDM_USERNAME "\",\"" MDM_PASSWORD "\",1"),
968 };
969 
970 /* Func: modem_pdp_context_active
971  * Desc: This helper function is called from modem_setup, and is
972  * used to open the PDP context. If there is trouble activating the
973  * PDP context, we try to deactivate and reactivate MDM_PDP_ACT_RETRY_COUNT times.
974  * If it fails, we return an error.
975  */
modem_pdp_context_activate(void)976 static int modem_pdp_context_activate(void)
977 {
978 	int ret;
979 	int retry_count = 0;
980 
981 	ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
982 			     NULL, 0U, "AT+QIACT=1", &mdata.sem_response,
983 			     MDM_CMD_TIMEOUT);
984 
985 	/* If there is trouble activating the PDP context, we try to deactivate/reactive it. */
986 	while (ret == -EIO && retry_count < MDM_PDP_ACT_RETRY_COUNT) {
987 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
988 			     NULL, 0U, "AT+QIDEACT=1", &mdata.sem_response,
989 			     MDM_CMD_TIMEOUT);
990 
991 		/* If there's any error for AT+QIDEACT, restart the module. */
992 		if (ret != 0) {
993 			return ret;
994 		}
995 
996 		ret = modem_cmd_send(&mctx.iface, &mctx.cmd_handler,
997 			     NULL, 0U, "AT+QIACT=1", &mdata.sem_response,
998 			     MDM_CMD_TIMEOUT);
999 
1000 		retry_count++;
1001 	}
1002 
1003 	if (ret == -EIO && retry_count >= MDM_PDP_ACT_RETRY_COUNT) {
1004 		LOG_ERR("Retried activating/deactivating too many times.");
1005 	}
1006 
1007 	return ret;
1008 }
1009 
1010 /* Func: modem_setup
1011  * Desc: This function is used to setup the modem from zero. The idea
1012  * is that this function will be called right after the modem is
1013  * powered on to do the stuff necessary to talk to the modem.
1014  */
modem_setup(void)1015 static int modem_setup(void)
1016 {
1017 	int ret = 0, counter;
1018 	int rssi_retry_count = 0, init_retry_count = 0;
1019 
1020 	/* Setup the pins to ensure that Modem is enabled. */
1021 	pin_init();
1022 
1023 restart:
1024 
1025 	counter = 0;
1026 
1027 	/* stop RSSI delay work */
1028 	k_work_cancel_delayable(&mdata.rssi_query_work);
1029 
1030 	/* Let the modem respond. */
1031 	LOG_INF("Waiting for modem to respond");
1032 	ret = k_sem_take(&mdata.sem_response, MDM_MAX_BOOT_TIME);
1033 	if (ret < 0) {
1034 		LOG_ERR("Timeout waiting for RDY");
1035 		goto error;
1036 	}
1037 
1038 	/* Run setup commands on the modem. */
1039 	ret = modem_cmd_handler_setup_cmds(&mctx.iface, &mctx.cmd_handler,
1040 					   setup_cmds, ARRAY_SIZE(setup_cmds),
1041 					   &mdata.sem_response, MDM_REGISTRATION_TIMEOUT);
1042 	if (ret < 0) {
1043 		goto error;
1044 	}
1045 
1046 restart_rssi:
1047 
1048 	/* query modem RSSI */
1049 	modem_rssi_query_work(NULL);
1050 	k_sleep(MDM_WAIT_FOR_RSSI_DELAY);
1051 
1052 	/* Keep trying to read RSSI until we get a valid value - Eventually, exit. */
1053 	while (counter++ < MDM_WAIT_FOR_RSSI_COUNT &&
1054 	      (mdata.mdm_rssi >= 0 || mdata.mdm_rssi <= -1000)) {
1055 		modem_rssi_query_work(NULL);
1056 		k_sleep(MDM_WAIT_FOR_RSSI_DELAY);
1057 	}
1058 
1059 	/* Is the RSSI invalid ? */
1060 	if (mdata.mdm_rssi >= 0 || mdata.mdm_rssi <= -1000) {
1061 		rssi_retry_count++;
1062 
1063 		if (rssi_retry_count >= MDM_NETWORK_RETRY_COUNT) {
1064 			LOG_ERR("Failed network init. Too many attempts!");
1065 			ret = -ENETUNREACH;
1066 			goto error;
1067 		}
1068 
1069 		/* Try again! */
1070 		LOG_ERR("Failed network init. Restarting process.");
1071 		counter = 0;
1072 		goto restart_rssi;
1073 	}
1074 
1075 	/* Network is ready - Start RSSI work in the background. */
1076 	LOG_INF("Network is ready.");
1077 	k_work_reschedule_for_queue(&modem_workq, &mdata.rssi_query_work,
1078 				    K_SECONDS(RSSI_TIMEOUT_SECS));
1079 
1080 	/* Once the network is ready, we try to activate the PDP context. */
1081 	ret = modem_pdp_context_activate();
1082 	if (ret < 0 && init_retry_count++ < MDM_INIT_RETRY_COUNT) {
1083 		LOG_ERR("Error activating modem with pdp context");
1084 		goto restart;
1085 	}
1086 
1087 error:
1088 	return ret;
1089 }
1090 
1091 static const struct socket_op_vtable offload_socket_fd_op_vtable = {
1092 	.fd_vtable = {
1093 		.read	= offload_read,
1094 		.write	= offload_write,
1095 		.close	= offload_close,
1096 		.ioctl	= offload_ioctl,
1097 	},
1098 	.bind		= NULL,
1099 	.connect	= offload_connect,
1100 	.sendto		= offload_sendto,
1101 	.recvfrom	= offload_recvfrom,
1102 	.listen		= NULL,
1103 	.accept		= NULL,
1104 	.sendmsg	= offload_sendmsg,
1105 	.getsockopt	= NULL,
1106 	.setsockopt	= NULL,
1107 };
1108 
1109 static int offload_socket(int family, int type, int proto);
1110 
1111 /* Setup the Modem NET Interface. */
modem_net_iface_init(struct net_if * iface)1112 static void modem_net_iface_init(struct net_if *iface)
1113 {
1114 	const struct device *dev = net_if_get_device(iface);
1115 	struct modem_data *data	 = dev->data;
1116 
1117 	/* Direct socket offload used instead of net offload: */
1118 	net_if_set_link_addr(iface, modem_get_mac(dev),
1119 			     sizeof(data->mac_addr),
1120 			     NET_LINK_ETHERNET);
1121 	data->net_iface = iface;
1122 
1123 	net_if_socket_offload_set(iface, offload_socket);
1124 }
1125 
1126 static struct offloaded_if_api api_funcs = {
1127 	.iface_api.init = modem_net_iface_init,
1128 };
1129 
offload_is_supported(int family,int type,int proto)1130 static bool offload_is_supported(int family, int type, int proto)
1131 {
1132 	if (family != AF_INET &&
1133 	    family != AF_INET6) {
1134 		return false;
1135 	}
1136 
1137 	if (type != SOCK_STREAM) {
1138 		return false;
1139 	}
1140 
1141 	if (proto != IPPROTO_TCP) {
1142 		return false;
1143 	}
1144 
1145 	return true;
1146 }
1147 
offload_socket(int family,int type,int proto)1148 static int offload_socket(int family, int type, int proto)
1149 {
1150 	int ret;
1151 
1152 	/* defer modem's socket create call to bind() */
1153 	ret = modem_socket_get(&mdata.socket_config, family, type, proto);
1154 	if (ret < 0) {
1155 		errno = -ret;
1156 		return -1;
1157 	}
1158 
1159 	errno = 0;
1160 	return ret;
1161 }
1162 
modem_init(const struct device * dev)1163 static int modem_init(const struct device *dev)
1164 {
1165 	int ret; ARG_UNUSED(dev);
1166 
1167 #if !DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
1168 	k_sem_init(&mdata.sem_pin_busy,	 1, 1);
1169 #endif /* !DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios) */
1170 	k_sem_init(&mdata.sem_response,	 0, 1);
1171 	k_sem_init(&mdata.sem_tx_ready,	 0, 1);
1172 	k_sem_init(&mdata.sem_sock_conn, 0, 1);
1173 	k_work_queue_start(&modem_workq, modem_workq_stack,
1174 			   K_KERNEL_STACK_SIZEOF(modem_workq_stack),
1175 			   K_PRIO_COOP(7), NULL);
1176 
1177 	/* socket config */
1178 	ret = modem_socket_init(&mdata.socket_config, &mdata.sockets[0], ARRAY_SIZE(mdata.sockets),
1179 				MDM_BASE_SOCKET_NUM, true, &offload_socket_fd_op_vtable);
1180 	if (ret < 0) {
1181 		goto error;
1182 	}
1183 
1184 	/* cmd handler setup */
1185 	const struct modem_cmd_handler_config cmd_handler_config = {
1186 		.match_buf = &mdata.cmd_match_buf[0],
1187 		.match_buf_len = sizeof(mdata.cmd_match_buf),
1188 		.buf_pool = &mdm_recv_pool,
1189 		.alloc_timeout = BUF_ALLOC_TIMEOUT,
1190 		.eol = "\r\n",
1191 		.user_data = NULL,
1192 		.response_cmds = response_cmds,
1193 		.response_cmds_len = ARRAY_SIZE(response_cmds),
1194 		.unsol_cmds = unsol_cmds,
1195 		.unsol_cmds_len = ARRAY_SIZE(unsol_cmds),
1196 	};
1197 
1198 	ret = modem_cmd_handler_init(&mctx.cmd_handler, &mdata.cmd_handler_data,
1199 				     &cmd_handler_config);
1200 	if (ret < 0) {
1201 		goto error;
1202 	}
1203 
1204 	/* modem interface */
1205 	const struct modem_iface_uart_config uart_config = {
1206 		.rx_rb_buf = &mdata.iface_rb_buf[0],
1207 		.rx_rb_buf_len = sizeof(mdata.iface_rb_buf),
1208 		.dev = MDM_UART_DEV,
1209 		.hw_flow_control = DT_PROP(MDM_UART_NODE, hw_flow_control),
1210 	};
1211 
1212 	ret = modem_iface_uart_init(&mctx.iface, &mdata.iface_data, &uart_config);
1213 	if (ret < 0) {
1214 		goto error;
1215 	}
1216 
1217 	/* modem data storage */
1218 	mctx.data_manufacturer = mdata.mdm_manufacturer;
1219 	mctx.data_model	       = mdata.mdm_model;
1220 	mctx.data_revision     = mdata.mdm_revision;
1221 	mctx.data_imei	       = mdata.mdm_imei;
1222 #if defined(CONFIG_MODEM_SIM_NUMBERS)
1223 	mctx.data_imsi	       = mdata.mdm_imsi;
1224 	mctx.data_iccid	       = mdata.mdm_iccid;
1225 #endif /* #if defined(CONFIG_MODEM_SIM_NUMBERS) */
1226 	mctx.data_rssi = &mdata.mdm_rssi;
1227 
1228 	/* pin setup */
1229 	ret = gpio_pin_configure_dt(&power_gpio, GPIO_OUTPUT_LOW);
1230 	if (ret < 0) {
1231 		LOG_ERR("Failed to configure %s pin", "power");
1232 		goto error;
1233 	}
1234 
1235 #if DT_INST_NODE_HAS_PROP(0, mdm_reset_gpios)
1236 	ret = gpio_pin_configure_dt(&reset_gpio, GPIO_OUTPUT_LOW);
1237 	if (ret < 0) {
1238 		LOG_ERR("Failed to configure %s pin", "reset");
1239 		goto error;
1240 	}
1241 #endif
1242 
1243 #if DT_INST_NODE_HAS_PROP(0, mdm_dtr_gpios)
1244 	ret = gpio_pin_configure_dt(&dtr_gpio, GPIO_OUTPUT_LOW);
1245 	if (ret < 0) {
1246 		LOG_ERR("Failed to configure %s pin", "dtr");
1247 		goto error;
1248 	}
1249 #endif
1250 
1251 #if DT_INST_NODE_HAS_PROP(0, mdm_wdisable_gpios)
1252 	ret = gpio_pin_configure_dt(&wdisable_gpio, GPIO_OUTPUT_LOW);
1253 	if (ret < 0) {
1254 		LOG_ERR("Failed to configure %s pin", "wdisable");
1255 		goto error;
1256 	}
1257 #endif
1258 
1259 	/* modem context setup */
1260 	mctx.driver_data       = &mdata;
1261 
1262 	ret = modem_context_register(&mctx);
1263 	if (ret < 0) {
1264 		LOG_ERR("Error registering modem context: %d", ret);
1265 		goto error;
1266 	}
1267 
1268 	/* start RX thread */
1269 	k_thread_create(&modem_rx_thread, modem_rx_stack,
1270 			K_KERNEL_STACK_SIZEOF(modem_rx_stack),
1271 			modem_rx,
1272 			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
1273 
1274 	/* Init RSSI query */
1275 	k_work_init_delayable(&mdata.rssi_query_work, modem_rssi_query_work);
1276 	return modem_setup();
1277 
1278 error:
1279 	return ret;
1280 }
1281 
1282 /* Register the device with the Networking stack. */
1283 NET_DEVICE_DT_INST_OFFLOAD_DEFINE(0, modem_init, NULL,
1284 				  &mdata, NULL,
1285 				  CONFIG_MODEM_QUECTEL_BG9X_INIT_PRIORITY,
1286 				  &api_funcs, MDM_MAX_DATA_LENGTH);
1287 
1288 /* Register NET sockets. */
1289 NET_SOCKET_OFFLOAD_REGISTER(quectel_bg9x, CONFIG_NET_SOCKETS_OFFLOAD_PRIORITY,
1290 			    AF_UNSPEC, offload_is_supported, offload_socket);
1291