1 /*
2 * Copyright (c) 2023 Bjarki Arge Andreasen
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/drivers/cellular.h>
11 #include <zephyr/drivers/uart.h>
12 #include <zephyr/modem/chat.h>
13 #include <zephyr/modem/cmux.h>
14 #include <zephyr/modem/pipe.h>
15 #include <zephyr/modem/pipelink.h>
16 #include <zephyr/modem/ppp.h>
17 #include <zephyr/modem/backend/uart.h>
18 #include <zephyr/net/ppp.h>
19 #include <zephyr/pm/device.h>
20 #include <zephyr/sys/atomic.h>
21
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(modem_cellular, CONFIG_MODEM_LOG_LEVEL);
24
25 #include <string.h>
26 #include <stdlib.h>
27
28 #define MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT \
29 K_MSEC(CONFIG_MODEM_CELLULAR_PERIODIC_SCRIPT_MS)
30
31 #define MODEM_CELLULAR_DATA_IMEI_LEN (16)
32 #define MODEM_CELLULAR_DATA_MODEL_ID_LEN (65)
33 #define MODEM_CELLULAR_DATA_IMSI_LEN (23)
34 #define MODEM_CELLULAR_DATA_ICCID_LEN (22)
35 #define MODEM_CELLULAR_DATA_MANUFACTURER_LEN (65)
36 #define MODEM_CELLULAR_DATA_FW_VERSION_LEN (65)
37
38 #define MODEM_CELLULAR_RESERVED_DLCIS (2)
39
40 /* Magic constants */
41 #define CSQ_RSSI_UNKNOWN (99)
42 #define CESQ_RSRP_UNKNOWN (255)
43 #define CESQ_RSRQ_UNKNOWN (255)
44
45 /* Magic numbers to units conversions */
46 #define CSQ_RSSI_TO_DB(v) (-113 + (2 * (rssi)))
47 #define CESQ_RSRP_TO_DB(v) (-140 + (v))
48 #define CESQ_RSRQ_TO_DB(v) (-20 + ((v) / 2))
49
50 enum modem_cellular_state {
51 MODEM_CELLULAR_STATE_IDLE = 0,
52 MODEM_CELLULAR_STATE_RESET_PULSE,
53 MODEM_CELLULAR_STATE_POWER_ON_PULSE,
54 MODEM_CELLULAR_STATE_AWAIT_POWER_ON,
55 MODEM_CELLULAR_STATE_SET_BAUDRATE,
56 MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT,
57 MODEM_CELLULAR_STATE_CONNECT_CMUX,
58 MODEM_CELLULAR_STATE_OPEN_DLCI1,
59 MODEM_CELLULAR_STATE_OPEN_DLCI2,
60 MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT,
61 MODEM_CELLULAR_STATE_AWAIT_REGISTERED,
62 MODEM_CELLULAR_STATE_CARRIER_ON,
63 MODEM_CELLULAR_STATE_INIT_POWER_OFF,
64 MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT,
65 MODEM_CELLULAR_STATE_POWER_OFF_PULSE,
66 MODEM_CELLULAR_STATE_AWAIT_POWER_OFF,
67 };
68
69 enum modem_cellular_event {
70 MODEM_CELLULAR_EVENT_RESUME = 0,
71 MODEM_CELLULAR_EVENT_SUSPEND,
72 MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS,
73 MODEM_CELLULAR_EVENT_SCRIPT_FAILED,
74 MODEM_CELLULAR_EVENT_CMUX_CONNECTED,
75 MODEM_CELLULAR_EVENT_DLCI1_OPENED,
76 MODEM_CELLULAR_EVENT_DLCI2_OPENED,
77 MODEM_CELLULAR_EVENT_TIMEOUT,
78 MODEM_CELLULAR_EVENT_REGISTERED,
79 MODEM_CELLULAR_EVENT_DEREGISTERED,
80 MODEM_CELLULAR_EVENT_BUS_OPENED,
81 MODEM_CELLULAR_EVENT_BUS_CLOSED,
82 };
83
84 struct modem_cellular_data {
85 /* UART backend */
86 struct modem_pipe *uart_pipe;
87 struct modem_backend_uart uart_backend;
88 uint8_t uart_backend_receive_buf[CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES];
89 uint8_t uart_backend_transmit_buf[CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES];
90
91 /* CMUX */
92 struct modem_cmux cmux;
93 uint8_t cmux_receive_buf[CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE];
94 uint8_t cmux_transmit_buf[2 * CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE];
95
96 struct modem_cmux_dlci dlci1;
97 struct modem_cmux_dlci dlci2;
98 struct modem_pipe *dlci1_pipe;
99 struct modem_pipe *dlci2_pipe;
100 /* Points to dlci2_pipe or NULL. Used for shutdown script if not NULL */
101 struct modem_pipe *cmd_pipe;
102 uint8_t dlci1_receive_buf[CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE];
103 /* DLCI 2 is only used for chat scripts. */
104 uint8_t dlci2_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZES];
105
106 /* Modem chat */
107 struct modem_chat chat;
108 uint8_t chat_receive_buf[CONFIG_MODEM_CELLULAR_CHAT_BUFFER_SIZES];
109 uint8_t *chat_delimiter;
110 uint8_t *chat_filter;
111 uint8_t *chat_argv[32];
112
113 /* Status */
114 enum cellular_registration_status registration_status_gsm;
115 enum cellular_registration_status registration_status_gprs;
116 enum cellular_registration_status registration_status_lte;
117 uint8_t rssi;
118 uint8_t rsrp;
119 uint8_t rsrq;
120 uint8_t imei[MODEM_CELLULAR_DATA_IMEI_LEN];
121 uint8_t model_id[MODEM_CELLULAR_DATA_MODEL_ID_LEN];
122 uint8_t imsi[MODEM_CELLULAR_DATA_IMSI_LEN];
123 uint8_t iccid[MODEM_CELLULAR_DATA_ICCID_LEN];
124 uint8_t manufacturer[MODEM_CELLULAR_DATA_MANUFACTURER_LEN];
125 uint8_t fw_version[MODEM_CELLULAR_DATA_FW_VERSION_LEN];
126
127 /* PPP */
128 struct modem_ppp *ppp;
129
130 enum modem_cellular_state state;
131 const struct device *dev;
132 struct k_work_delayable timeout_work;
133
134 /* Power management */
135 struct k_sem suspended_sem;
136
137 /* Event dispatcher */
138 struct k_work event_dispatch_work;
139 uint8_t event_buf[8];
140 struct ring_buf event_rb;
141 struct k_mutex event_rb_lock;
142 };
143
144 struct modem_cellular_user_pipe {
145 struct modem_cmux_dlci dlci;
146 uint8_t dlci_address;
147 uint8_t *dlci_receive_buf;
148 uint16_t dlci_receive_buf_size;
149 struct modem_pipe *pipe;
150 struct modem_pipelink *pipelink;
151 };
152
153 struct modem_cellular_config {
154 const struct device *uart;
155 struct gpio_dt_spec power_gpio;
156 struct gpio_dt_spec reset_gpio;
157 uint16_t power_pulse_duration_ms;
158 uint16_t reset_pulse_duration_ms;
159 uint16_t startup_time_ms;
160 uint16_t shutdown_time_ms;
161 bool autostarts;
162 const struct modem_chat_script *init_chat_script;
163 const struct modem_chat_script *dial_chat_script;
164 const struct modem_chat_script *periodic_chat_script;
165 const struct modem_chat_script *shutdown_chat_script;
166 const struct modem_chat_script *set_baudrate_chat_script;
167 struct modem_cellular_user_pipe *user_pipes;
168 uint8_t user_pipes_size;
169 };
170
modem_cellular_state_str(enum modem_cellular_state state)171 static const char *modem_cellular_state_str(enum modem_cellular_state state)
172 {
173 switch (state) {
174 case MODEM_CELLULAR_STATE_IDLE:
175 return "idle";
176 case MODEM_CELLULAR_STATE_RESET_PULSE:
177 return "reset pulse";
178 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
179 return "power pulse";
180 case MODEM_CELLULAR_STATE_AWAIT_POWER_ON:
181 return "await power on";
182 case MODEM_CELLULAR_STATE_SET_BAUDRATE:
183 return "set baudrate";
184 case MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT:
185 return "run init script";
186 case MODEM_CELLULAR_STATE_CONNECT_CMUX:
187 return "connect cmux";
188 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
189 return "open dlci1";
190 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
191 return "open dlci2";
192 case MODEM_CELLULAR_STATE_AWAIT_REGISTERED:
193 return "await registered";
194 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
195 return "run dial script";
196 case MODEM_CELLULAR_STATE_CARRIER_ON:
197 return "carrier on";
198 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
199 return "init power off";
200 case MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT:
201 return "run shutdown script";
202 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
203 return "power off pulse";
204 case MODEM_CELLULAR_STATE_AWAIT_POWER_OFF:
205 return "await power off";
206 }
207
208 return "";
209 }
210
modem_cellular_event_str(enum modem_cellular_event event)211 static const char *modem_cellular_event_str(enum modem_cellular_event event)
212 {
213 switch (event) {
214 case MODEM_CELLULAR_EVENT_RESUME:
215 return "resume";
216 case MODEM_CELLULAR_EVENT_SUSPEND:
217 return "suspend";
218 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
219 return "script success";
220 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
221 return "script failed";
222 case MODEM_CELLULAR_EVENT_CMUX_CONNECTED:
223 return "cmux connected";
224 case MODEM_CELLULAR_EVENT_DLCI1_OPENED:
225 return "dlci1 opened";
226 case MODEM_CELLULAR_EVENT_DLCI2_OPENED:
227 return "dlci2 opened";
228 case MODEM_CELLULAR_EVENT_TIMEOUT:
229 return "timeout";
230 case MODEM_CELLULAR_EVENT_REGISTERED:
231 return "registered";
232 case MODEM_CELLULAR_EVENT_DEREGISTERED:
233 return "deregistered";
234 case MODEM_CELLULAR_EVENT_BUS_OPENED:
235 return "bus opened";
236 case MODEM_CELLULAR_EVENT_BUS_CLOSED:
237 return "bus closed";
238 }
239
240 return "";
241 }
242
modem_cellular_gpio_is_enabled(const struct gpio_dt_spec * gpio)243 static bool modem_cellular_gpio_is_enabled(const struct gpio_dt_spec *gpio)
244 {
245 return gpio->port != NULL;
246 }
247
modem_cellular_notify_user_pipes_connected(struct modem_cellular_data * data)248 static void modem_cellular_notify_user_pipes_connected(struct modem_cellular_data *data)
249 {
250 const struct modem_cellular_config *config =
251 (const struct modem_cellular_config *)data->dev->config;
252 struct modem_cellular_user_pipe *user_pipe;
253 struct modem_pipelink *pipelink;
254
255 for (uint8_t i = 0; i < config->user_pipes_size; i++) {
256 user_pipe = &config->user_pipes[i];
257 pipelink = user_pipe->pipelink;
258 modem_pipelink_notify_connected(pipelink);
259 }
260 }
261
modem_cellular_notify_user_pipes_disconnected(struct modem_cellular_data * data)262 static void modem_cellular_notify_user_pipes_disconnected(struct modem_cellular_data *data)
263 {
264 const struct modem_cellular_config *config =
265 (const struct modem_cellular_config *)data->dev->config;
266 struct modem_cellular_user_pipe *user_pipe;
267 struct modem_pipelink *pipelink;
268
269 for (uint8_t i = 0; i < config->user_pipes_size; i++) {
270 user_pipe = &config->user_pipes[i];
271 pipelink = user_pipe->pipelink;
272 modem_pipelink_notify_disconnected(pipelink);
273 }
274 }
275
276 static void modem_cellular_enter_state(struct modem_cellular_data *data,
277 enum modem_cellular_state state);
278
279 static void modem_cellular_delegate_event(struct modem_cellular_data *data,
280 enum modem_cellular_event evt);
281
282 static void modem_cellular_event_handler(struct modem_cellular_data *data,
283 enum modem_cellular_event evt);
284
modem_cellular_bus_pipe_handler(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)285 static void modem_cellular_bus_pipe_handler(struct modem_pipe *pipe,
286 enum modem_pipe_event event,
287 void *user_data)
288 {
289 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
290
291 switch (event) {
292 case MODEM_PIPE_EVENT_OPENED:
293 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_BUS_OPENED);
294 break;
295
296 case MODEM_PIPE_EVENT_CLOSED:
297 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_BUS_CLOSED);
298 break;
299
300 default:
301 break;
302 }
303 }
304
modem_cellular_dlci1_pipe_handler(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)305 static void modem_cellular_dlci1_pipe_handler(struct modem_pipe *pipe,
306 enum modem_pipe_event event,
307 void *user_data)
308 {
309 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
310
311 switch (event) {
312 case MODEM_PIPE_EVENT_OPENED:
313 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_DLCI1_OPENED);
314 break;
315
316 default:
317 break;
318 }
319 }
320
modem_cellular_dlci2_pipe_handler(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)321 static void modem_cellular_dlci2_pipe_handler(struct modem_pipe *pipe,
322 enum modem_pipe_event event,
323 void *user_data)
324 {
325 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
326
327 switch (event) {
328 case MODEM_PIPE_EVENT_OPENED:
329 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_DLCI2_OPENED);
330 break;
331
332 default:
333 break;
334 }
335 }
336
modem_cellular_chat_callback_handler(struct modem_chat * chat,enum modem_chat_script_result result,void * user_data)337 static void modem_cellular_chat_callback_handler(struct modem_chat *chat,
338 enum modem_chat_script_result result,
339 void *user_data)
340 {
341 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
342
343 if (result == MODEM_CHAT_SCRIPT_RESULT_SUCCESS) {
344 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS);
345 } else {
346 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_SCRIPT_FAILED);
347 }
348 }
349
modem_cellular_chat_on_imei(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)350 static void modem_cellular_chat_on_imei(struct modem_chat *chat, char **argv, uint16_t argc,
351 void *user_data)
352 {
353 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
354
355 if (argc != 2) {
356 return;
357 }
358
359 strncpy(data->imei, argv[1], sizeof(data->imei) - 1);
360 }
361
modem_cellular_chat_on_cgmm(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)362 static void modem_cellular_chat_on_cgmm(struct modem_chat *chat, char **argv, uint16_t argc,
363 void *user_data)
364 {
365 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
366
367 if (argc != 2) {
368 return;
369 }
370
371 strncpy(data->model_id, argv[1], sizeof(data->model_id) - 1);
372 }
373
modem_cellular_chat_on_cgmi(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)374 static void modem_cellular_chat_on_cgmi(struct modem_chat *chat, char **argv, uint16_t argc,
375 void *user_data)
376 {
377 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
378
379 if (argc != 2) {
380 return;
381 }
382
383 strncpy(data->manufacturer, argv[1], sizeof(data->manufacturer) - 1);
384 }
385
modem_cellular_chat_on_cgmr(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)386 static void modem_cellular_chat_on_cgmr(struct modem_chat *chat, char **argv, uint16_t argc,
387 void *user_data)
388 {
389 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
390
391 if (argc != 2) {
392 return;
393 }
394
395 strncpy(data->fw_version, argv[1], sizeof(data->fw_version) - 1);
396 }
397
modem_cellular_chat_on_csq(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)398 static void modem_cellular_chat_on_csq(struct modem_chat *chat, char **argv, uint16_t argc,
399 void *user_data)
400 {
401 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
402
403 if (argc != 3) {
404 return;
405 }
406
407 data->rssi = (uint8_t)atoi(argv[1]);
408 }
409
modem_cellular_chat_on_cesq(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)410 static void modem_cellular_chat_on_cesq(struct modem_chat *chat, char **argv, uint16_t argc,
411 void *user_data)
412 {
413 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
414
415 if (argc != 7) {
416 return;
417 }
418
419 data->rsrq = (uint8_t)atoi(argv[5]);
420 data->rsrp = (uint8_t)atoi(argv[6]);
421 }
422
modem_cellular_chat_on_iccid(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)423 static void modem_cellular_chat_on_iccid(struct modem_chat *chat, char **argv, uint16_t argc,
424 void *user_data)
425 {
426 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
427
428 if (argc != 2) {
429 return;
430 }
431
432 strncpy(data->iccid, argv[1], sizeof(data->iccid) - 1);
433 }
434
modem_cellular_chat_on_imsi(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)435 static void modem_cellular_chat_on_imsi(struct modem_chat *chat, char **argv, uint16_t argc,
436 void *user_data)
437 {
438 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
439
440 if (argc != 2) {
441 return;
442 }
443
444 strncpy(data->imsi, argv[1], sizeof(data->imsi) - 1);
445 }
446
modem_cellular_is_registered(struct modem_cellular_data * data)447 static bool modem_cellular_is_registered(struct modem_cellular_data *data)
448 {
449 return (data->registration_status_gsm == CELLULAR_REGISTRATION_REGISTERED_HOME)
450 || (data->registration_status_gsm == CELLULAR_REGISTRATION_REGISTERED_ROAMING)
451 || (data->registration_status_gprs == CELLULAR_REGISTRATION_REGISTERED_HOME)
452 || (data->registration_status_gprs == CELLULAR_REGISTRATION_REGISTERED_ROAMING)
453 || (data->registration_status_lte == CELLULAR_REGISTRATION_REGISTERED_HOME)
454 || (data->registration_status_lte == CELLULAR_REGISTRATION_REGISTERED_ROAMING);
455 }
456
modem_cellular_chat_on_cxreg(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)457 static void modem_cellular_chat_on_cxreg(struct modem_chat *chat, char **argv, uint16_t argc,
458 void *user_data)
459 {
460 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
461 enum cellular_registration_status registration_status = 0;
462
463 /* This receives both +C*REG? read command answers and unsolicited notifications.
464 * Their syntax differs in that the former has one more parameter, <n>, which is first.
465 */
466 if (argc >= 3 && argv[2][0] != '"') {
467 /* +CEREG: <n>,<stat>[,<tac>[...]] */
468 registration_status = atoi(argv[2]);
469 } else if (argc >= 2) {
470 /* +CEREG: <stat>[,<tac>[...]] */
471 registration_status = atoi(argv[1]);
472 } else {
473 return;
474 }
475
476 if (strcmp(argv[0], "+CREG: ") == 0) {
477 data->registration_status_gsm = registration_status;
478 } else if (strcmp(argv[0], "+CGREG: ") == 0) {
479 data->registration_status_gprs = registration_status;
480 } else { /* CEREG */
481 data->registration_status_lte = registration_status;
482 }
483
484 if (modem_cellular_is_registered(data)) {
485 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_REGISTERED);
486 } else {
487 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_DEREGISTERED);
488 }
489 }
490
491 MODEM_CHAT_MATCH_DEFINE(ok_match, "OK", "", NULL);
492 MODEM_CHAT_MATCHES_DEFINE(allow_match,
493 MODEM_CHAT_MATCH("OK", "", NULL),
494 MODEM_CHAT_MATCH("ERROR", "", NULL));
495
496 MODEM_CHAT_MATCH_DEFINE(imei_match, "", "", modem_cellular_chat_on_imei);
497 MODEM_CHAT_MATCH_DEFINE(cgmm_match, "", "", modem_cellular_chat_on_cgmm);
498 MODEM_CHAT_MATCH_DEFINE(csq_match, "+CSQ: ", ",", modem_cellular_chat_on_csq);
499 MODEM_CHAT_MATCH_DEFINE(cesq_match, "+CESQ: ", ",", modem_cellular_chat_on_cesq);
500 MODEM_CHAT_MATCH_DEFINE(qccid_match __maybe_unused, "+QCCID: ", "", modem_cellular_chat_on_iccid);
501 MODEM_CHAT_MATCH_DEFINE(iccid_match __maybe_unused, "+ICCID: ", "", modem_cellular_chat_on_iccid);
502 MODEM_CHAT_MATCH_DEFINE(cimi_match __maybe_unused, "", "", modem_cellular_chat_on_imsi);
503 MODEM_CHAT_MATCH_DEFINE(cgmi_match __maybe_unused, "", "", modem_cellular_chat_on_cgmi);
504 MODEM_CHAT_MATCH_DEFINE(cgmr_match __maybe_unused, "", "", modem_cellular_chat_on_cgmr);
505
506 MODEM_CHAT_MATCHES_DEFINE(unsol_matches,
507 MODEM_CHAT_MATCH("+CREG: ", ",", modem_cellular_chat_on_cxreg),
508 MODEM_CHAT_MATCH("+CEREG: ", ",", modem_cellular_chat_on_cxreg),
509 MODEM_CHAT_MATCH("+CGREG: ", ",", modem_cellular_chat_on_cxreg));
510
511 MODEM_CHAT_MATCHES_DEFINE(abort_matches, MODEM_CHAT_MATCH("ERROR", "", NULL));
512
513 MODEM_CHAT_MATCHES_DEFINE(dial_abort_matches,
514 MODEM_CHAT_MATCH("ERROR", "", NULL),
515 MODEM_CHAT_MATCH("BUSY", "", NULL),
516 MODEM_CHAT_MATCH("NO ANSWER", "", NULL),
517 MODEM_CHAT_MATCH("NO CARRIER", "", NULL),
518 MODEM_CHAT_MATCH("NO DIALTONE", "", NULL));
519
520 #if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800) || DT_HAS_COMPAT_STATUS_OKAY(sqn_gm02s)
521 MODEM_CHAT_MATCH_DEFINE(connect_match, "CONNECT", "", NULL);
522 #endif
523
modem_cellular_log_state_changed(enum modem_cellular_state last_state,enum modem_cellular_state new_state)524 static void modem_cellular_log_state_changed(enum modem_cellular_state last_state,
525 enum modem_cellular_state new_state)
526 {
527 LOG_DBG("switch from %s to %s", modem_cellular_state_str(last_state),
528 modem_cellular_state_str(new_state));
529 }
530
modem_cellular_log_event(enum modem_cellular_event evt)531 static void modem_cellular_log_event(enum modem_cellular_event evt)
532 {
533 LOG_DBG("event %s", modem_cellular_event_str(evt));
534 }
535
modem_cellular_start_timer(struct modem_cellular_data * data,k_timeout_t timeout)536 static void modem_cellular_start_timer(struct modem_cellular_data *data, k_timeout_t timeout)
537 {
538 k_work_schedule(&data->timeout_work, timeout);
539 }
540
modem_cellular_stop_timer(struct modem_cellular_data * data)541 static void modem_cellular_stop_timer(struct modem_cellular_data *data)
542 {
543 k_work_cancel_delayable(&data->timeout_work);
544 }
545
modem_cellular_timeout_handler(struct k_work * item)546 static void modem_cellular_timeout_handler(struct k_work *item)
547 {
548 struct k_work_delayable *dwork = k_work_delayable_from_work(item);
549 struct modem_cellular_data *data =
550 CONTAINER_OF(dwork, struct modem_cellular_data, timeout_work);
551
552 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_TIMEOUT);
553 }
554
modem_cellular_event_dispatch_handler(struct k_work * item)555 static void modem_cellular_event_dispatch_handler(struct k_work *item)
556 {
557 struct modem_cellular_data *data =
558 CONTAINER_OF(item, struct modem_cellular_data, event_dispatch_work);
559
560 uint8_t events[sizeof(data->event_buf)];
561 uint8_t events_cnt;
562
563 k_mutex_lock(&data->event_rb_lock, K_FOREVER);
564
565 events_cnt = (uint8_t)ring_buf_get(&data->event_rb, events, sizeof(data->event_buf));
566
567 k_mutex_unlock(&data->event_rb_lock);
568
569 for (uint8_t i = 0; i < events_cnt; i++) {
570 modem_cellular_event_handler(data, (enum modem_cellular_event)events[i]);
571 }
572 }
573
modem_cellular_delegate_event(struct modem_cellular_data * data,enum modem_cellular_event evt)574 static void modem_cellular_delegate_event(struct modem_cellular_data *data,
575 enum modem_cellular_event evt)
576 {
577 k_mutex_lock(&data->event_rb_lock, K_FOREVER);
578 ring_buf_put(&data->event_rb, (uint8_t *)&evt, 1);
579 k_mutex_unlock(&data->event_rb_lock);
580 k_work_submit(&data->event_dispatch_work);
581 }
582
modem_cellular_begin_power_off_pulse(struct modem_cellular_data * data)583 static void modem_cellular_begin_power_off_pulse(struct modem_cellular_data *data)
584 {
585 const struct modem_cellular_config *config =
586 (const struct modem_cellular_config *)data->dev->config;
587
588 modem_pipe_close_async(data->uart_pipe);
589
590 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
591 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_POWER_OFF_PULSE);
592 } else {
593 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
594 }
595 }
596
modem_cellular_on_idle_state_enter(struct modem_cellular_data * data)597 static int modem_cellular_on_idle_state_enter(struct modem_cellular_data *data)
598 {
599 const struct modem_cellular_config *config =
600 (const struct modem_cellular_config *)data->dev->config;
601
602 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
603 gpio_pin_set_dt(&config->reset_gpio, 1);
604 }
605
606 modem_cellular_notify_user_pipes_disconnected(data);
607 modem_chat_release(&data->chat);
608 modem_ppp_release(data->ppp);
609 modem_cmux_release(&data->cmux);
610 modem_pipe_close_async(data->uart_pipe);
611 k_sem_give(&data->suspended_sem);
612 return 0;
613 }
614
modem_cellular_idle_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)615 static void modem_cellular_idle_event_handler(struct modem_cellular_data *data,
616 enum modem_cellular_event evt)
617 {
618 const struct modem_cellular_config *config =
619 (const struct modem_cellular_config *)data->dev->config;
620
621 switch (evt) {
622 case MODEM_CELLULAR_EVENT_RESUME:
623 if (config->autostarts) {
624 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
625 break;
626 }
627
628 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
629 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_POWER_ON_PULSE);
630 break;
631 }
632
633 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
634 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
635 break;
636 }
637
638 if (config->set_baudrate_chat_script != NULL) {
639 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_SET_BAUDRATE);
640 } else {
641 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT);
642 }
643 break;
644
645 case MODEM_CELLULAR_EVENT_SUSPEND:
646 k_sem_give(&data->suspended_sem);
647 break;
648
649 default:
650 break;
651 }
652 }
653
modem_cellular_on_idle_state_leave(struct modem_cellular_data * data)654 static int modem_cellular_on_idle_state_leave(struct modem_cellular_data *data)
655 {
656 const struct modem_cellular_config *config =
657 (const struct modem_cellular_config *)data->dev->config;
658
659 k_sem_take(&data->suspended_sem, K_NO_WAIT);
660
661 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
662 gpio_pin_set_dt(&config->reset_gpio, 0);
663 }
664
665 return 0;
666 }
667
modem_cellular_on_reset_pulse_state_enter(struct modem_cellular_data * data)668 static int modem_cellular_on_reset_pulse_state_enter(struct modem_cellular_data *data)
669 {
670 const struct modem_cellular_config *config =
671 (const struct modem_cellular_config *)data->dev->config;
672
673 gpio_pin_set_dt(&config->reset_gpio, 1);
674 modem_cellular_start_timer(data, K_MSEC(config->reset_pulse_duration_ms));
675 return 0;
676 }
677
modem_cellular_reset_pulse_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)678 static void modem_cellular_reset_pulse_event_handler(struct modem_cellular_data *data,
679 enum modem_cellular_event evt)
680 {
681 switch (evt) {
682 case MODEM_CELLULAR_EVENT_TIMEOUT:
683 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
684 break;
685
686 case MODEM_CELLULAR_EVENT_SUSPEND:
687 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
688 break;
689
690 default:
691 break;
692 }
693 }
694
modem_cellular_on_reset_pulse_state_leave(struct modem_cellular_data * data)695 static int modem_cellular_on_reset_pulse_state_leave(struct modem_cellular_data *data)
696 {
697 const struct modem_cellular_config *config =
698 (const struct modem_cellular_config *)data->dev->config;
699
700 gpio_pin_set_dt(&config->reset_gpio, 0);
701 modem_cellular_stop_timer(data);
702 return 0;
703 }
704
modem_cellular_on_power_on_pulse_state_enter(struct modem_cellular_data * data)705 static int modem_cellular_on_power_on_pulse_state_enter(struct modem_cellular_data *data)
706 {
707 const struct modem_cellular_config *config =
708 (const struct modem_cellular_config *)data->dev->config;
709
710 gpio_pin_set_dt(&config->power_gpio, 1);
711 modem_cellular_start_timer(data, K_MSEC(config->power_pulse_duration_ms));
712 return 0;
713 }
714
modem_cellular_power_on_pulse_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)715 static void modem_cellular_power_on_pulse_event_handler(struct modem_cellular_data *data,
716 enum modem_cellular_event evt)
717 {
718 switch (evt) {
719 case MODEM_CELLULAR_EVENT_TIMEOUT:
720 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
721 break;
722
723 case MODEM_CELLULAR_EVENT_SUSPEND:
724 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
725 break;
726
727 default:
728 break;
729 }
730 }
731
modem_cellular_on_power_on_pulse_state_leave(struct modem_cellular_data * data)732 static int modem_cellular_on_power_on_pulse_state_leave(struct modem_cellular_data *data)
733 {
734 const struct modem_cellular_config *config =
735 (const struct modem_cellular_config *)data->dev->config;
736
737 gpio_pin_set_dt(&config->power_gpio, 0);
738 modem_cellular_stop_timer(data);
739 return 0;
740 }
741
modem_cellular_on_await_power_on_state_enter(struct modem_cellular_data * data)742 static int modem_cellular_on_await_power_on_state_enter(struct modem_cellular_data *data)
743 {
744 const struct modem_cellular_config *config =
745 (const struct modem_cellular_config *)data->dev->config;
746
747 modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
748 return 0;
749 }
750
modem_cellular_await_power_on_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)751 static void modem_cellular_await_power_on_event_handler(struct modem_cellular_data *data,
752 enum modem_cellular_event evt)
753 {
754 const struct modem_cellular_config *config =
755 (const struct modem_cellular_config *)data->dev->config;
756
757 switch (evt) {
758 case MODEM_CELLULAR_EVENT_TIMEOUT:
759 if (config->set_baudrate_chat_script != NULL) {
760 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_SET_BAUDRATE);
761 } else {
762 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT);
763 }
764 break;
765
766 case MODEM_CELLULAR_EVENT_SUSPEND:
767 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
768 break;
769
770 default:
771 break;
772 }
773 }
774
modem_cellular_on_set_baudrate_state_enter(struct modem_cellular_data * data)775 static int modem_cellular_on_set_baudrate_state_enter(struct modem_cellular_data *data)
776 {
777 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
778 return modem_pipe_open_async(data->uart_pipe);
779 }
780
modem_cellular_set_baudrate_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)781 static void modem_cellular_set_baudrate_event_handler(struct modem_cellular_data *data,
782 enum modem_cellular_event evt)
783 {
784 const struct modem_cellular_config *config =
785 (const struct modem_cellular_config *)data->dev->config;
786 struct uart_config cfg = {0};
787 int ret;
788
789 switch (evt) {
790 case MODEM_CELLULAR_EVENT_BUS_OPENED:
791 modem_chat_attach(&data->chat, data->uart_pipe);
792 modem_chat_run_script_async(&data->chat, config->set_baudrate_chat_script);
793 break;
794
795 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
796 /* Let modem reconfigure */
797 modem_cellular_start_timer(data, K_MSEC(CONFIG_MODEM_CELLULAR_NEW_BAUDRATE_DELAY));
798 break;
799 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
800 /* Some modems save the new speed on first change, meaning the
801 * modem is already at the new baudrate, meaning no reply. So
802 * ignore any failures and continue as if baudrate is already set
803 */
804 LOG_DBG("no reply from modem, assuming baudrate is already set");
805 __fallthrough;
806 case MODEM_CELLULAR_EVENT_TIMEOUT:
807 modem_chat_release(&data->chat);
808 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
809 modem_pipe_close_async(data->uart_pipe);
810
811 ret = uart_config_get(config->uart, &cfg);
812 if (ret < 0) {
813 LOG_ERR("Failed to get UART configuration (%d)", ret);
814 break;
815 }
816 cfg.baudrate = CONFIG_MODEM_CELLULAR_NEW_BAUDRATE;
817 ret = uart_configure(config->uart, &cfg);
818 if (ret < 0) {
819 LOG_ERR("Failed to set new baudrate (%d)", ret);
820 break;
821 }
822 break;
823
824 case MODEM_CELLULAR_EVENT_BUS_CLOSED:
825 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT);
826 break;
827
828 case MODEM_CELLULAR_EVENT_SUSPEND:
829 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
830 break;
831
832 default:
833 break;
834 }
835 }
836
modem_cellular_on_run_init_script_state_enter(struct modem_cellular_data * data)837 static int modem_cellular_on_run_init_script_state_enter(struct modem_cellular_data *data)
838 {
839 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
840 return modem_pipe_open_async(data->uart_pipe);
841 }
842
modem_cellular_run_init_script_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)843 static void modem_cellular_run_init_script_event_handler(struct modem_cellular_data *data,
844 enum modem_cellular_event evt)
845 {
846 const struct modem_cellular_config *config =
847 (const struct modem_cellular_config *)data->dev->config;
848
849 switch (evt) {
850 case MODEM_CELLULAR_EVENT_BUS_OPENED:
851 modem_chat_attach(&data->chat, data->uart_pipe);
852 modem_chat_run_script_async(&data->chat, config->init_chat_script);
853 break;
854
855 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
856 net_if_set_link_addr(modem_ppp_get_iface(data->ppp), data->imei,
857 ARRAY_SIZE(data->imei), NET_LINK_UNKNOWN);
858
859 modem_chat_release(&data->chat);
860 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
861 modem_pipe_close_async(data->uart_pipe);
862 break;
863
864 case MODEM_CELLULAR_EVENT_BUS_CLOSED:
865 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CONNECT_CMUX);
866 break;
867
868 case MODEM_CELLULAR_EVENT_SUSPEND:
869 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
870 break;
871
872 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
873 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
874 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_POWER_ON_PULSE);
875 break;
876 }
877
878 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
879 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
880 break;
881 }
882
883 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
884 break;
885
886 default:
887 break;
888 }
889 }
890
modem_cellular_on_connect_cmux_state_enter(struct modem_cellular_data * data)891 static int modem_cellular_on_connect_cmux_state_enter(struct modem_cellular_data *data)
892 {
893 /*
894 * Allow modem to switch bus into CMUX mode. Some modems disable UART RX while
895 * switching, resulting in UART RX errors as bus is no longer pulled up by modem.
896 */
897 modem_cellular_start_timer(data, K_MSEC(100));
898 return 0;
899 }
900
modem_cellular_connect_cmux_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)901 static void modem_cellular_connect_cmux_event_handler(struct modem_cellular_data *data,
902 enum modem_cellular_event evt)
903 {
904 switch (evt) {
905 case MODEM_CELLULAR_EVENT_TIMEOUT:
906 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
907 modem_pipe_open_async(data->uart_pipe);
908 break;
909
910 case MODEM_CELLULAR_EVENT_BUS_OPENED:
911 modem_cmux_attach(&data->cmux, data->uart_pipe);
912 modem_cmux_connect_async(&data->cmux);
913 break;
914
915 case MODEM_CELLULAR_EVENT_CMUX_CONNECTED:
916 modem_cellular_notify_user_pipes_connected(data);
917 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_OPEN_DLCI1);
918 break;
919
920 case MODEM_CELLULAR_EVENT_SUSPEND:
921 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
922 break;
923
924 default:
925 break;
926 }
927 }
928
modem_cellular_on_open_dlci1_state_enter(struct modem_cellular_data * data)929 static int modem_cellular_on_open_dlci1_state_enter(struct modem_cellular_data *data)
930 {
931 modem_pipe_attach(data->dlci1_pipe, modem_cellular_dlci1_pipe_handler, data);
932 return modem_pipe_open_async(data->dlci1_pipe);
933 }
934
modem_cellular_open_dlci1_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)935 static void modem_cellular_open_dlci1_event_handler(struct modem_cellular_data *data,
936 enum modem_cellular_event evt)
937 {
938 switch (evt) {
939 case MODEM_CELLULAR_EVENT_DLCI1_OPENED:
940 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_OPEN_DLCI2);
941 break;
942
943 case MODEM_CELLULAR_EVENT_SUSPEND:
944 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
945 break;
946
947 default:
948 break;
949 }
950 }
951
modem_cellular_on_open_dlci1_state_leave(struct modem_cellular_data * data)952 static int modem_cellular_on_open_dlci1_state_leave(struct modem_cellular_data *data)
953 {
954 modem_pipe_release(data->dlci1_pipe);
955 return 0;
956 }
957
modem_cellular_on_open_dlci2_state_enter(struct modem_cellular_data * data)958 static int modem_cellular_on_open_dlci2_state_enter(struct modem_cellular_data *data)
959 {
960 modem_pipe_attach(data->dlci2_pipe, modem_cellular_dlci2_pipe_handler, data);
961 return modem_pipe_open_async(data->dlci2_pipe);
962 }
963
modem_cellular_open_dlci2_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)964 static void modem_cellular_open_dlci2_event_handler(struct modem_cellular_data *data,
965 enum modem_cellular_event evt)
966 {
967 switch (evt) {
968 case MODEM_CELLULAR_EVENT_DLCI2_OPENED:
969 data->cmd_pipe = data->dlci2_pipe;
970 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
971 break;
972
973 case MODEM_CELLULAR_EVENT_SUSPEND:
974 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
975 break;
976
977 default:
978 break;
979 }
980 }
981
modem_cellular_on_open_dlci2_state_leave(struct modem_cellular_data * data)982 static int modem_cellular_on_open_dlci2_state_leave(struct modem_cellular_data *data)
983 {
984 modem_pipe_release(data->dlci2_pipe);
985 return 0;
986 }
987
modem_cellular_on_run_dial_script_state_enter(struct modem_cellular_data * data)988 static int modem_cellular_on_run_dial_script_state_enter(struct modem_cellular_data *data)
989 {
990 /* Allow modem time to enter command mode before running dial script */
991 modem_cellular_start_timer(data, K_MSEC(100));
992 return 0;
993 }
994
modem_cellular_run_dial_script_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)995 static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_data *data,
996 enum modem_cellular_event evt)
997 {
998 const struct modem_cellular_config *config =
999 (const struct modem_cellular_config *)data->dev->config;
1000
1001 switch (evt) {
1002 case MODEM_CELLULAR_EVENT_TIMEOUT:
1003 modem_chat_attach(&data->chat, data->dlci1_pipe);
1004 modem_chat_run_script_async(&data->chat, config->dial_chat_script);
1005 break;
1006
1007 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
1008 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_REGISTERED);
1009 break;
1010
1011 case MODEM_CELLULAR_EVENT_SUSPEND:
1012 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
1013 break;
1014
1015 default:
1016 break;
1017 }
1018 }
1019
modem_cellular_on_run_dial_script_state_leave(struct modem_cellular_data * data)1020 static int modem_cellular_on_run_dial_script_state_leave(struct modem_cellular_data *data)
1021 {
1022 modem_chat_release(&data->chat);
1023 return 0;
1024 }
1025
modem_cellular_on_await_registered_state_enter(struct modem_cellular_data * data)1026 static int modem_cellular_on_await_registered_state_enter(struct modem_cellular_data *data)
1027 {
1028 if (modem_ppp_attach(data->ppp, data->dlci1_pipe) < 0) {
1029 return -EAGAIN;
1030 }
1031
1032 modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT);
1033 return modem_chat_attach(&data->chat, data->dlci2_pipe);
1034 }
1035
modem_cellular_await_registered_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1036 static void modem_cellular_await_registered_event_handler(struct modem_cellular_data *data,
1037 enum modem_cellular_event evt)
1038 {
1039 const struct modem_cellular_config *config =
1040 (const struct modem_cellular_config *)data->dev->config;
1041
1042 switch (evt) {
1043 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
1044 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
1045 modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT);
1046 break;
1047
1048 case MODEM_CELLULAR_EVENT_TIMEOUT:
1049 modem_chat_run_script_async(&data->chat, config->periodic_chat_script);
1050 break;
1051
1052 case MODEM_CELLULAR_EVENT_REGISTERED:
1053 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CARRIER_ON);
1054 break;
1055
1056 case MODEM_CELLULAR_EVENT_SUSPEND:
1057 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
1058 break;
1059
1060 default:
1061 break;
1062 }
1063 }
1064
modem_cellular_on_await_registered_state_leave(struct modem_cellular_data * data)1065 static int modem_cellular_on_await_registered_state_leave(struct modem_cellular_data *data)
1066 {
1067 modem_cellular_stop_timer(data);
1068 return 0;
1069 }
1070
modem_cellular_on_carrier_on_state_enter(struct modem_cellular_data * data)1071 static int modem_cellular_on_carrier_on_state_enter(struct modem_cellular_data *data)
1072 {
1073 net_if_carrier_on(modem_ppp_get_iface(data->ppp));
1074 modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT);
1075 return 0;
1076 }
1077
modem_cellular_carrier_on_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1078 static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *data,
1079 enum modem_cellular_event evt)
1080 {
1081 const struct modem_cellular_config *config =
1082 (const struct modem_cellular_config *)data->dev->config;
1083
1084 switch (evt) {
1085 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
1086 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
1087 modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT);
1088 break;
1089
1090 case MODEM_CELLULAR_EVENT_TIMEOUT:
1091 modem_chat_run_script_async(&data->chat, config->periodic_chat_script);
1092 break;
1093
1094 case MODEM_CELLULAR_EVENT_DEREGISTERED:
1095 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
1096 break;
1097
1098 case MODEM_CELLULAR_EVENT_SUSPEND:
1099 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
1100 break;
1101
1102 default:
1103 break;
1104 }
1105 }
1106
modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data * data)1107 static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data *data)
1108 {
1109 modem_cellular_stop_timer(data);
1110 net_if_carrier_off(modem_ppp_get_iface(data->ppp));
1111 modem_chat_release(&data->chat);
1112 modem_ppp_release(data->ppp);
1113 return 0;
1114 }
1115
modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data * data)1116 static int modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data *data)
1117 {
1118 modem_cellular_start_timer(data, K_MSEC(2000));
1119 return 0;
1120 }
1121
modem_cellular_init_power_off_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1122 static void modem_cellular_init_power_off_event_handler(struct modem_cellular_data *data,
1123 enum modem_cellular_event evt)
1124 {
1125 const struct modem_cellular_config *config =
1126 (const struct modem_cellular_config *)data->dev->config;
1127
1128 switch (evt) {
1129 case MODEM_CELLULAR_EVENT_TIMEOUT:
1130 /* Shutdown script can only be used if cmd_pipe is available, i.e. we are not in
1131 * some intermediary state without a pipe for commands available
1132 */
1133 if (config->shutdown_chat_script != NULL && data->cmd_pipe != NULL) {
1134 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT);
1135 break;
1136 }
1137
1138 modem_cellular_begin_power_off_pulse(data);
1139 break;
1140
1141 default:
1142 break;
1143 }
1144 }
1145
modem_cellular_on_init_power_off_state_leave(struct modem_cellular_data * data)1146 static int modem_cellular_on_init_power_off_state_leave(struct modem_cellular_data *data)
1147 {
1148 modem_cellular_notify_user_pipes_disconnected(data);
1149 modem_chat_release(&data->chat);
1150 modem_ppp_release(data->ppp);
1151 return 0;
1152 }
1153
modem_cellular_on_run_shutdown_script_state_enter(struct modem_cellular_data * data)1154 static int modem_cellular_on_run_shutdown_script_state_enter(struct modem_cellular_data *data)
1155 {
1156 const struct modem_cellular_config *config =
1157 (const struct modem_cellular_config *)data->dev->config;
1158
1159 modem_chat_attach(&data->chat, data->cmd_pipe);
1160 return modem_chat_run_script_async(&data->chat, config->shutdown_chat_script);
1161 }
1162
modem_cellular_run_shutdown_script_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1163 static void modem_cellular_run_shutdown_script_event_handler(struct modem_cellular_data *data,
1164 enum modem_cellular_event evt)
1165 {
1166 switch (evt) {
1167 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
1168 data->cmd_pipe = NULL;
1169
1170 /* If shutdown by software failed, try by power pulse if possible */
1171 modem_cellular_begin_power_off_pulse(data);
1172
1173 break;
1174
1175 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
1176 modem_pipe_close_async(data->uart_pipe);
1177 data->cmd_pipe = NULL;
1178 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
1179 break;
1180
1181 default:
1182 break;
1183 }
1184 }
1185
modem_cellular_on_run_shutdown_script_state_leave(struct modem_cellular_data * data)1186 static int modem_cellular_on_run_shutdown_script_state_leave(struct modem_cellular_data *data)
1187 {
1188 modem_chat_release(&data->chat);
1189 return 0;
1190 }
1191
modem_cellular_on_power_off_pulse_state_enter(struct modem_cellular_data * data)1192 static int modem_cellular_on_power_off_pulse_state_enter(struct modem_cellular_data *data)
1193 {
1194 const struct modem_cellular_config *config =
1195 (const struct modem_cellular_config *)data->dev->config;
1196
1197 data->cmd_pipe = NULL;
1198 gpio_pin_set_dt(&config->power_gpio, 1);
1199 modem_cellular_start_timer(data, K_MSEC(config->power_pulse_duration_ms));
1200 return 0;
1201 }
1202
modem_cellular_power_off_pulse_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1203 static void modem_cellular_power_off_pulse_event_handler(struct modem_cellular_data *data,
1204 enum modem_cellular_event evt)
1205 {
1206 switch (evt) {
1207 case MODEM_CELLULAR_EVENT_TIMEOUT:
1208 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_OFF);
1209 break;
1210
1211 default:
1212 break;
1213 }
1214 }
1215
modem_cellular_on_power_off_pulse_state_leave(struct modem_cellular_data * data)1216 static int modem_cellular_on_power_off_pulse_state_leave(struct modem_cellular_data *data)
1217 {
1218 const struct modem_cellular_config *config =
1219 (const struct modem_cellular_config *)data->dev->config;
1220
1221 gpio_pin_set_dt(&config->power_gpio, 0);
1222 modem_cellular_stop_timer(data);
1223 return 0;
1224 }
1225
modem_cellular_on_await_power_off_state_enter(struct modem_cellular_data * data)1226 static int modem_cellular_on_await_power_off_state_enter(struct modem_cellular_data *data)
1227 {
1228 const struct modem_cellular_config *config =
1229 (const struct modem_cellular_config *)data->dev->config;
1230
1231 modem_cellular_start_timer(data, K_MSEC(config->shutdown_time_ms));
1232 return 0;
1233 }
1234
modem_cellular_await_power_off_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1235 static void modem_cellular_await_power_off_event_handler(struct modem_cellular_data *data,
1236 enum modem_cellular_event evt)
1237 {
1238 switch (evt) {
1239 case MODEM_CELLULAR_EVENT_TIMEOUT:
1240 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
1241 break;
1242
1243 default:
1244 break;
1245 }
1246 }
1247
modem_cellular_on_state_enter(struct modem_cellular_data * data)1248 static int modem_cellular_on_state_enter(struct modem_cellular_data *data)
1249 {
1250 int ret;
1251
1252 switch (data->state) {
1253 case MODEM_CELLULAR_STATE_IDLE:
1254 ret = modem_cellular_on_idle_state_enter(data);
1255 break;
1256
1257 case MODEM_CELLULAR_STATE_RESET_PULSE:
1258 ret = modem_cellular_on_reset_pulse_state_enter(data);
1259 break;
1260
1261 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
1262 ret = modem_cellular_on_power_on_pulse_state_enter(data);
1263 break;
1264
1265 case MODEM_CELLULAR_STATE_AWAIT_POWER_ON:
1266 ret = modem_cellular_on_await_power_on_state_enter(data);
1267 break;
1268
1269 case MODEM_CELLULAR_STATE_SET_BAUDRATE:
1270 ret = modem_cellular_on_set_baudrate_state_enter(data);
1271 break;
1272
1273 case MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT:
1274 ret = modem_cellular_on_run_init_script_state_enter(data);
1275 break;
1276
1277 case MODEM_CELLULAR_STATE_CONNECT_CMUX:
1278 ret = modem_cellular_on_connect_cmux_state_enter(data);
1279 break;
1280
1281 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
1282 ret = modem_cellular_on_open_dlci1_state_enter(data);
1283 break;
1284
1285 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
1286 ret = modem_cellular_on_open_dlci2_state_enter(data);
1287 break;
1288
1289 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
1290 ret = modem_cellular_on_run_dial_script_state_enter(data);
1291 break;
1292
1293 case MODEM_CELLULAR_STATE_AWAIT_REGISTERED:
1294 ret = modem_cellular_on_await_registered_state_enter(data);
1295 break;
1296
1297 case MODEM_CELLULAR_STATE_CARRIER_ON:
1298 ret = modem_cellular_on_carrier_on_state_enter(data);
1299 break;
1300
1301 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
1302 ret = modem_cellular_on_init_power_off_state_enter(data);
1303 break;
1304
1305 case MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT:
1306 ret = modem_cellular_on_run_shutdown_script_state_enter(data);
1307 break;
1308
1309 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
1310 ret = modem_cellular_on_power_off_pulse_state_enter(data);
1311 break;
1312
1313 case MODEM_CELLULAR_STATE_AWAIT_POWER_OFF:
1314 ret = modem_cellular_on_await_power_off_state_enter(data);
1315 break;
1316
1317 default:
1318 ret = 0;
1319 break;
1320 }
1321
1322 return ret;
1323 }
1324
modem_cellular_on_state_leave(struct modem_cellular_data * data)1325 static int modem_cellular_on_state_leave(struct modem_cellular_data *data)
1326 {
1327 int ret;
1328
1329 switch (data->state) {
1330 case MODEM_CELLULAR_STATE_IDLE:
1331 ret = modem_cellular_on_idle_state_leave(data);
1332 break;
1333
1334 case MODEM_CELLULAR_STATE_RESET_PULSE:
1335 ret = modem_cellular_on_reset_pulse_state_leave(data);
1336 break;
1337
1338 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
1339 ret = modem_cellular_on_power_on_pulse_state_leave(data);
1340 break;
1341
1342 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
1343 ret = modem_cellular_on_open_dlci1_state_leave(data);
1344 break;
1345
1346 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
1347 ret = modem_cellular_on_open_dlci2_state_leave(data);
1348 break;
1349
1350 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
1351 ret = modem_cellular_on_run_dial_script_state_leave(data);
1352 break;
1353
1354 case MODEM_CELLULAR_STATE_AWAIT_REGISTERED:
1355 ret = modem_cellular_on_await_registered_state_leave(data);
1356 break;
1357
1358 case MODEM_CELLULAR_STATE_CARRIER_ON:
1359 ret = modem_cellular_on_carrier_on_state_leave(data);
1360 break;
1361
1362 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
1363 ret = modem_cellular_on_init_power_off_state_leave(data);
1364 break;
1365
1366 case MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT:
1367 ret = modem_cellular_on_run_shutdown_script_state_leave(data);
1368 break;
1369
1370 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
1371 ret = modem_cellular_on_power_off_pulse_state_leave(data);
1372 break;
1373
1374 default:
1375 ret = 0;
1376 break;
1377 }
1378
1379 return ret;
1380 }
1381
modem_cellular_enter_state(struct modem_cellular_data * data,enum modem_cellular_state state)1382 static void modem_cellular_enter_state(struct modem_cellular_data *data,
1383 enum modem_cellular_state state)
1384 {
1385 int ret;
1386
1387 ret = modem_cellular_on_state_leave(data);
1388
1389 if (ret < 0) {
1390 LOG_WRN("failed to leave state, error: %i", ret);
1391
1392 return;
1393 }
1394
1395 data->state = state;
1396 ret = modem_cellular_on_state_enter(data);
1397
1398 if (ret < 0) {
1399 LOG_WRN("failed to enter state error: %i", ret);
1400 }
1401 }
1402
modem_cellular_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1403 static void modem_cellular_event_handler(struct modem_cellular_data *data,
1404 enum modem_cellular_event evt)
1405 {
1406 enum modem_cellular_state state;
1407
1408 state = data->state;
1409
1410 modem_cellular_log_event(evt);
1411
1412 switch (data->state) {
1413 case MODEM_CELLULAR_STATE_IDLE:
1414 modem_cellular_idle_event_handler(data, evt);
1415 break;
1416
1417 case MODEM_CELLULAR_STATE_RESET_PULSE:
1418 modem_cellular_reset_pulse_event_handler(data, evt);
1419 break;
1420
1421 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
1422 modem_cellular_power_on_pulse_event_handler(data, evt);
1423 break;
1424
1425 case MODEM_CELLULAR_STATE_AWAIT_POWER_ON:
1426 modem_cellular_await_power_on_event_handler(data, evt);
1427 break;
1428
1429 case MODEM_CELLULAR_STATE_SET_BAUDRATE:
1430 modem_cellular_set_baudrate_event_handler(data, evt);
1431 break;
1432
1433 case MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT:
1434 modem_cellular_run_init_script_event_handler(data, evt);
1435 break;
1436
1437 case MODEM_CELLULAR_STATE_CONNECT_CMUX:
1438 modem_cellular_connect_cmux_event_handler(data, evt);
1439 break;
1440
1441 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
1442 modem_cellular_open_dlci1_event_handler(data, evt);
1443 break;
1444
1445 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
1446 modem_cellular_open_dlci2_event_handler(data, evt);
1447 break;
1448
1449 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
1450 modem_cellular_run_dial_script_event_handler(data, evt);
1451 break;
1452
1453 case MODEM_CELLULAR_STATE_AWAIT_REGISTERED:
1454 modem_cellular_await_registered_event_handler(data, evt);
1455 break;
1456
1457 case MODEM_CELLULAR_STATE_CARRIER_ON:
1458 modem_cellular_carrier_on_event_handler(data, evt);
1459 break;
1460
1461 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
1462 modem_cellular_init_power_off_event_handler(data, evt);
1463 break;
1464
1465 case MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT:
1466 modem_cellular_run_shutdown_script_event_handler(data, evt);
1467 break;
1468
1469 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
1470 modem_cellular_power_off_pulse_event_handler(data, evt);
1471 break;
1472
1473 case MODEM_CELLULAR_STATE_AWAIT_POWER_OFF:
1474 modem_cellular_await_power_off_event_handler(data, evt);
1475 break;
1476 }
1477
1478 if (state != data->state) {
1479 modem_cellular_log_state_changed(state, data->state);
1480 }
1481 }
1482
modem_cellular_cmux_handler(struct modem_cmux * cmux,enum modem_cmux_event event,void * user_data)1483 static void modem_cellular_cmux_handler(struct modem_cmux *cmux, enum modem_cmux_event event,
1484 void *user_data)
1485 {
1486 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
1487
1488 switch (event) {
1489 case MODEM_CMUX_EVENT_CONNECTED:
1490 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_CMUX_CONNECTED);
1491 break;
1492
1493 default:
1494 break;
1495 }
1496 }
1497
1498 MODEM_CHAT_SCRIPT_CMDS_DEFINE(get_signal_csq_chat_script_cmds,
1499 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match),
1500 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match));
1501
1502 MODEM_CHAT_SCRIPT_DEFINE(get_signal_csq_chat_script, get_signal_csq_chat_script_cmds,
1503 abort_matches, modem_cellular_chat_callback_handler, 2);
1504
modem_cellular_csq_parse_rssi(uint8_t rssi,int16_t * value)1505 static inline int modem_cellular_csq_parse_rssi(uint8_t rssi, int16_t *value)
1506 {
1507 /* AT+CSQ returns a response +CSQ: <rssi>,<ber> where:
1508 * - rssi is a integer from 0 to 31 whose values describes a signal strength
1509 * between -113 dBm for 0 and -51dbM for 31 or unknown for 99
1510 * - ber is an integer from 0 to 7 that describes the error rate, it can also
1511 * be 99 for an unknown error rate
1512 */
1513 if (rssi == CSQ_RSSI_UNKNOWN) {
1514 return -EINVAL;
1515 }
1516
1517 *value = (int16_t)CSQ_RSSI_TO_DB(rssi);
1518 return 0;
1519 }
1520
1521 MODEM_CHAT_SCRIPT_CMDS_DEFINE(get_signal_cesq_chat_script_cmds,
1522 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CESQ", cesq_match),
1523 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match));
1524
1525 MODEM_CHAT_SCRIPT_DEFINE(get_signal_cesq_chat_script, get_signal_cesq_chat_script_cmds,
1526 abort_matches, modem_cellular_chat_callback_handler, 2);
1527
1528 /* AT+CESQ returns a response +CESQ: <rxlev>,<ber>,<rscp>,<ecn0>,<rsrq>,<rsrp> where:
1529 * - rsrq is a integer from 0 to 34 whose values describes the Reference Signal Receive
1530 * Quality between -20 dB for 0 and -3 dB for 34 (0.5 dB steps), or unknown for 255
1531 * - rsrp is an integer from 0 to 97 that describes the Reference Signal Receive Power
1532 * between -140 dBm for 0 and -44 dBm for 97 (1 dBm steps), or unknown for 255
1533 */
modem_cellular_cesq_parse_rsrp(uint8_t rsrp,int16_t * value)1534 static inline int modem_cellular_cesq_parse_rsrp(uint8_t rsrp, int16_t *value)
1535 {
1536 if (rsrp == CESQ_RSRP_UNKNOWN) {
1537 return -EINVAL;
1538 }
1539
1540 *value = (int16_t)CESQ_RSRP_TO_DB(rsrp);
1541 return 0;
1542 }
1543
modem_cellular_cesq_parse_rsrq(uint8_t rsrq,int16_t * value)1544 static inline int modem_cellular_cesq_parse_rsrq(uint8_t rsrq, int16_t *value)
1545 {
1546 if (rsrq == CESQ_RSRQ_UNKNOWN) {
1547 return -EINVAL;
1548 }
1549
1550 *value = (int16_t)CESQ_RSRQ_TO_DB(rsrq);
1551 return 0;
1552 }
1553
modem_cellular_get_signal(const struct device * dev,const enum cellular_signal_type type,int16_t * value)1554 static int modem_cellular_get_signal(const struct device *dev,
1555 const enum cellular_signal_type type,
1556 int16_t *value)
1557 {
1558 int ret = -ENOTSUP;
1559 struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
1560
1561 if ((data->state != MODEM_CELLULAR_STATE_AWAIT_REGISTERED) &&
1562 (data->state != MODEM_CELLULAR_STATE_CARRIER_ON)) {
1563 return -ENODATA;
1564 }
1565
1566 /* Run chat script */
1567 switch (type) {
1568 case CELLULAR_SIGNAL_RSSI:
1569 ret = modem_chat_run_script(&data->chat, &get_signal_csq_chat_script);
1570 break;
1571
1572 case CELLULAR_SIGNAL_RSRP:
1573 case CELLULAR_SIGNAL_RSRQ:
1574 ret = modem_chat_run_script(&data->chat, &get_signal_cesq_chat_script);
1575 break;
1576
1577 default:
1578 ret = -ENOTSUP;
1579 break;
1580 }
1581
1582 /* Verify chat script ran successfully */
1583 if (ret < 0) {
1584 return ret;
1585 }
1586
1587 /* Parse received value */
1588 switch (type) {
1589 case CELLULAR_SIGNAL_RSSI:
1590 ret = modem_cellular_csq_parse_rssi(data->rssi, value);
1591 break;
1592
1593 case CELLULAR_SIGNAL_RSRP:
1594 ret = modem_cellular_cesq_parse_rsrp(data->rsrp, value);
1595 break;
1596
1597 case CELLULAR_SIGNAL_RSRQ:
1598 ret = modem_cellular_cesq_parse_rsrq(data->rsrq, value);
1599 break;
1600
1601 default:
1602 ret = -ENOTSUP;
1603 break;
1604 }
1605
1606 return ret;
1607 }
1608
modem_cellular_get_modem_info(const struct device * dev,enum cellular_modem_info_type type,char * info,size_t size)1609 static int modem_cellular_get_modem_info(const struct device *dev,
1610 enum cellular_modem_info_type type,
1611 char *info, size_t size)
1612 {
1613 int ret = 0;
1614 struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
1615
1616 switch (type) {
1617 case CELLULAR_MODEM_INFO_IMEI:
1618 strncpy(info, &data->imei[0], MIN(size, sizeof(data->imei)));
1619 break;
1620 case CELLULAR_MODEM_INFO_SIM_IMSI:
1621 strncpy(info, &data->imsi[0], MIN(size, sizeof(data->imsi)));
1622 break;
1623 case CELLULAR_MODEM_INFO_MANUFACTURER:
1624 strncpy(info, &data->manufacturer[0], MIN(size, sizeof(data->manufacturer)));
1625 break;
1626 case CELLULAR_MODEM_INFO_FW_VERSION:
1627 strncpy(info, &data->fw_version[0], MIN(size, sizeof(data->fw_version)));
1628 break;
1629 case CELLULAR_MODEM_INFO_MODEL_ID:
1630 strncpy(info, &data->model_id[0], MIN(size, sizeof(data->model_id)));
1631 break;
1632 case CELLULAR_MODEM_INFO_SIM_ICCID:
1633 strncpy(info, &data->iccid[0], MIN(size, sizeof(data->iccid)));
1634 break;
1635 default:
1636 ret = -ENODATA;
1637 break;
1638 }
1639
1640 return ret;
1641 }
modem_cellular_get_registration_status(const struct device * dev,enum cellular_access_technology tech,enum cellular_registration_status * status)1642 static int modem_cellular_get_registration_status(const struct device *dev,
1643 enum cellular_access_technology tech,
1644 enum cellular_registration_status *status)
1645 {
1646 int ret = 0;
1647 struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
1648
1649 switch (tech) {
1650 case CELLULAR_ACCESS_TECHNOLOGY_GSM:
1651 *status = data->registration_status_gsm;
1652 break;
1653 case CELLULAR_ACCESS_TECHNOLOGY_GPRS:
1654 case CELLULAR_ACCESS_TECHNOLOGY_UMTS:
1655 case CELLULAR_ACCESS_TECHNOLOGY_EDGE:
1656 *status = data->registration_status_gprs;
1657 break;
1658 case CELLULAR_ACCESS_TECHNOLOGY_LTE:
1659 case CELLULAR_ACCESS_TECHNOLOGY_LTE_CAT_M1:
1660 case CELLULAR_ACCESS_TECHNOLOGY_LTE_CAT_M2:
1661 case CELLULAR_ACCESS_TECHNOLOGY_NB_IOT:
1662 *status = data->registration_status_lte;
1663 break;
1664 default:
1665 ret = -ENODATA;
1666 break;
1667 }
1668
1669 return ret;
1670 }
1671
1672 static DEVICE_API(cellular, modem_cellular_api) = {
1673 .get_signal = modem_cellular_get_signal,
1674 .get_modem_info = modem_cellular_get_modem_info,
1675 .get_registration_status = modem_cellular_get_registration_status,
1676 };
1677
1678 #ifdef CONFIG_PM_DEVICE
modem_cellular_pm_action(const struct device * dev,enum pm_device_action action)1679 static int modem_cellular_pm_action(const struct device *dev, enum pm_device_action action)
1680 {
1681 struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
1682 int ret;
1683
1684 switch (action) {
1685 case PM_DEVICE_ACTION_RESUME:
1686 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
1687 ret = 0;
1688 break;
1689
1690 case PM_DEVICE_ACTION_SUSPEND:
1691 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_SUSPEND);
1692 ret = k_sem_take(&data->suspended_sem, K_SECONDS(30));
1693 break;
1694
1695 default:
1696 ret = -ENOTSUP;
1697 break;
1698 }
1699
1700 return ret;
1701 }
1702 #endif /* CONFIG_PM_DEVICE */
1703
modem_cellular_init(const struct device * dev)1704 static int modem_cellular_init(const struct device *dev)
1705 {
1706 struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
1707 struct modem_cellular_config *config = (struct modem_cellular_config *)dev->config;
1708
1709 data->dev = dev;
1710
1711 k_work_init_delayable(&data->timeout_work, modem_cellular_timeout_handler);
1712
1713 k_work_init(&data->event_dispatch_work, modem_cellular_event_dispatch_handler);
1714 ring_buf_init(&data->event_rb, sizeof(data->event_buf), data->event_buf);
1715
1716 k_sem_init(&data->suspended_sem, 0, 1);
1717
1718 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
1719 gpio_pin_configure_dt(&config->power_gpio, GPIO_OUTPUT_INACTIVE);
1720 }
1721
1722 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
1723 gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE);
1724 }
1725
1726 {
1727 const struct modem_backend_uart_config uart_backend_config = {
1728 .uart = config->uart,
1729 .receive_buf = data->uart_backend_receive_buf,
1730 .receive_buf_size = ARRAY_SIZE(data->uart_backend_receive_buf),
1731 .transmit_buf = data->uart_backend_transmit_buf,
1732 .transmit_buf_size = ARRAY_SIZE(data->uart_backend_transmit_buf),
1733 };
1734
1735 data->uart_pipe = modem_backend_uart_init(&data->uart_backend,
1736 &uart_backend_config);
1737
1738 data->cmd_pipe = NULL;
1739 }
1740
1741 {
1742 const struct modem_cmux_config cmux_config = {
1743 .callback = modem_cellular_cmux_handler,
1744 .user_data = data,
1745 .receive_buf = data->cmux_receive_buf,
1746 .receive_buf_size = ARRAY_SIZE(data->cmux_receive_buf),
1747 .transmit_buf = data->cmux_transmit_buf,
1748 .transmit_buf_size = ARRAY_SIZE(data->cmux_transmit_buf),
1749 };
1750
1751 modem_cmux_init(&data->cmux, &cmux_config);
1752 }
1753
1754 {
1755 const struct modem_cmux_dlci_config dlci1_config = {
1756 .dlci_address = 1,
1757 .receive_buf = data->dlci1_receive_buf,
1758 .receive_buf_size = ARRAY_SIZE(data->dlci1_receive_buf),
1759 };
1760
1761 data->dlci1_pipe = modem_cmux_dlci_init(&data->cmux, &data->dlci1,
1762 &dlci1_config);
1763 }
1764
1765 {
1766 const struct modem_cmux_dlci_config dlci2_config = {
1767 .dlci_address = 2,
1768 .receive_buf = data->dlci2_receive_buf,
1769 .receive_buf_size = ARRAY_SIZE(data->dlci2_receive_buf),
1770 };
1771
1772 data->dlci2_pipe = modem_cmux_dlci_init(&data->cmux, &data->dlci2,
1773 &dlci2_config);
1774 }
1775
1776 for (uint8_t i = 0; i < config->user_pipes_size; i++) {
1777 struct modem_cellular_user_pipe *user_pipe = &config->user_pipes[i];
1778 const struct modem_cmux_dlci_config user_dlci_config = {
1779 .dlci_address = user_pipe->dlci_address,
1780 .receive_buf = user_pipe->dlci_receive_buf,
1781 .receive_buf_size = user_pipe->dlci_receive_buf_size,
1782 };
1783
1784 user_pipe->pipe = modem_cmux_dlci_init(&data->cmux, &user_pipe->dlci,
1785 &user_dlci_config);
1786
1787 modem_pipelink_init(user_pipe->pipelink, user_pipe->pipe);
1788 }
1789
1790 {
1791 const struct modem_chat_config chat_config = {
1792 .user_data = data,
1793 .receive_buf = data->chat_receive_buf,
1794 .receive_buf_size = ARRAY_SIZE(data->chat_receive_buf),
1795 .delimiter = data->chat_delimiter,
1796 .delimiter_size = strlen(data->chat_delimiter),
1797 .filter = data->chat_filter,
1798 .filter_size = data->chat_filter ? strlen(data->chat_filter) : 0,
1799 .argv = data->chat_argv,
1800 .argv_size = ARRAY_SIZE(data->chat_argv),
1801 .unsol_matches = unsol_matches,
1802 .unsol_matches_size = ARRAY_SIZE(unsol_matches),
1803 };
1804
1805 modem_chat_init(&data->chat, &chat_config);
1806 }
1807
1808 #ifndef CONFIG_PM_DEVICE
1809 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
1810 #else
1811 pm_device_init_suspended(dev);
1812 #endif /* CONFIG_PM_DEVICE */
1813
1814 return 0;
1815 }
1816
1817 /*
1818 * Every modem uses two custom scripts to initialize the modem and dial out.
1819 *
1820 * The first script is named <dt driver compatible>_init_chat_script, with its
1821 * script commands named <dt driver compatible>_init_chat_script_cmds. This
1822 * script is sent to the modem after it has started up, and must configure the
1823 * modem to use CMUX.
1824 *
1825 * The second script is named <dt driver compatible>_dial_chat_script, with its
1826 * script commands named <dt driver compatible>_dial_chat_script_cmds. This
1827 * script is sent on a DLCI channel in command mode, and must request the modem
1828 * dial out and put the DLCI channel into data mode.
1829 */
1830
1831 #if DT_HAS_COMPAT_STATUS_OKAY(quectel_bg95)
1832 MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_init_chat_script_cmds,
1833 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1834 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1835 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1836 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1837 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1838 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1839 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1840 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1841 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1842 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1843 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1844 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1845 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1846 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
1847 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1848 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
1849 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1850 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
1851 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1852 MODEM_CHAT_SCRIPT_CMD_RESP("AT+QCCID", qccid_match),
1853 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1854 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300));
1855
1856 MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_init_chat_script, quectel_bg95_init_chat_script_cmds,
1857 abort_matches, modem_cellular_chat_callback_handler, 10);
1858
1859 MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_dial_chat_script_cmds,
1860 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1861 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1862 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1863 ok_match),
1864 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1865 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
1866
1867 MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_dial_chat_script, quectel_bg95_dial_chat_script_cmds,
1868 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1869
1870 MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_periodic_chat_script_cmds,
1871 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1872 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1873 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
1874
1875 MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_periodic_chat_script,
1876 quectel_bg95_periodic_chat_script_cmds, abort_matches,
1877 modem_cellular_chat_callback_handler, 4);
1878 #endif
1879
1880 #if DT_HAS_COMPAT_STATUS_OKAY(quectel_eg25_g)
1881 MODEM_CHAT_SCRIPT_CMDS_DEFINE(
1882 quectel_eg25_g_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1883 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1884 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1885 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1886 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1887 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1888 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1889 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1890 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1891 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1892 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1893 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1894 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1895 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
1896 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1897 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
1898 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1899 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
1900 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1901 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", 100));
1902
1903 MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_init_chat_script, quectel_eg25_g_init_chat_script_cmds,
1904 abort_matches, modem_cellular_chat_callback_handler, 10);
1905
1906 MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_dial_chat_script_cmds,
1907 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1908 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1909 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1910 ok_match),
1911 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1912 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
1913
1914 MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_dial_chat_script, quectel_eg25_g_dial_chat_script_cmds,
1915 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1916
1917 MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_periodic_chat_script_cmds,
1918 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1919 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1920 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1921 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match));
1922
1923 MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_periodic_chat_script,
1924 quectel_eg25_g_periodic_chat_script_cmds, abort_matches,
1925 modem_cellular_chat_callback_handler, 4);
1926 #endif
1927
1928 #if DT_HAS_COMPAT_STATUS_OKAY(simcom_sim7080)
1929 MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_init_chat_script_cmds,
1930 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1931 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1932 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1933 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1934 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1935 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1936 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1937 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1938 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1939 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1940 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1941 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1942 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1943 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1944 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1945 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1946 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1947 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300));
1948
1949 MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_init_chat_script, simcom_sim7080_init_chat_script_cmds,
1950 abort_matches, modem_cellular_chat_callback_handler, 10);
1951
1952 MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_dial_chat_script_cmds,
1953 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1954 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1955 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1956 ok_match),
1957 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1958 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
1959
1960 MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_dial_chat_script, simcom_sim7080_dial_chat_script_cmds,
1961 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1962
1963 MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_periodic_chat_script_cmds,
1964 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1965 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1966 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
1967
1968 MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_periodic_chat_script,
1969 simcom_sim7080_periodic_chat_script_cmds, abort_matches,
1970 modem_cellular_chat_callback_handler, 4);
1971 #endif
1972
1973 #if DT_HAS_COMPAT_STATUS_OKAY(u_blox_sara_r4)
1974 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_init_chat_script_cmds,
1975 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1976 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1977 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1978 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1979 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1980 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1981 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1982 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1983 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1984 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1985 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1986 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1987 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1988 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1989 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1990 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1991 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1992 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,127", ok_match));
1993
1994 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_init_chat_script, u_blox_sara_r4_init_chat_script_cmds,
1995 abort_matches, modem_cellular_chat_callback_handler, 10);
1996
1997 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_dial_chat_script_cmds,
1998 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1999 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
2000 "\""CONFIG_MODEM_CELLULAR_APN"\"",
2001 ok_match),
2002 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
2003 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
2004
2005 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_dial_chat_script, u_blox_sara_r4_dial_chat_script_cmds,
2006 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
2007
2008 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_periodic_chat_script_cmds,
2009 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2010 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2011 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
2012
2013 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_periodic_chat_script,
2014 u_blox_sara_r4_periodic_chat_script_cmds, abort_matches,
2015 modem_cellular_chat_callback_handler, 4);
2016 #endif
2017
2018 #if DT_HAS_COMPAT_STATUS_OKAY(u_blox_sara_r5)
2019 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r5_init_chat_script_cmds,
2020 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2021 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2022 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2023 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2024 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
2025 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
2026 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
2027 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
2028 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
2029 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
2030 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2031 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2032 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
2033 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
2034 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2035 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
2036 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2037 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
2038 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2039 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
2040 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2041 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
2042 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2043 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,127", ok_match));
2044
2045 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r5_init_chat_script, u_blox_sara_r5_init_chat_script_cmds,
2046 abort_matches, modem_cellular_chat_callback_handler, 10);
2047
2048 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r5_dial_chat_script_cmds,
2049 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
2050 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
2051 "\""CONFIG_MODEM_CELLULAR_APN"\"",
2052 ok_match),
2053 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
2054 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
2055
2056 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r5_dial_chat_script, u_blox_sara_r5_dial_chat_script_cmds,
2057 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
2058
2059 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r5_periodic_chat_script_cmds,
2060 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2061 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2062 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
2063
2064 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r5_periodic_chat_script,
2065 u_blox_sara_r5_periodic_chat_script_cmds, abort_matches,
2066 modem_cellular_chat_callback_handler, 4);
2067 #endif
2068
2069 #if DT_HAS_COMPAT_STATUS_OKAY(u_blox_lara_r6)
2070 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_lara_r6_set_baudrate_chat_script_cmds,
2071 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
2072 MODEM_CHAT_SCRIPT_CMD_RESP("AT+IPR="
2073 STRINGIFY(CONFIG_MODEM_CELLULAR_NEW_BAUDRATE), ok_match));
2074
2075 MODEM_CHAT_SCRIPT_DEFINE(u_blox_lara_r6_set_baudrate_chat_script,
2076 u_blox_lara_r6_set_baudrate_chat_script_cmds,
2077 abort_matches, modem_cellular_chat_callback_handler, 1);
2078
2079 /* NOTE: For some reason, a CMUX max frame size of 127 causes FCS errors in
2080 * this modem; larger or smaller doesn't. The modem's default value is 31,
2081 * which works well
2082 */
2083 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_lara_r6_init_chat_script_cmds,
2084 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
2085 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
2086 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
2087 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
2088 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
2089 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2090 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2091 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
2092 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
2093 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2094 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
2095 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2096 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
2097 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2098 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
2099 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2100 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
2101 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2102 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,31", ok_match));
2103
2104 MODEM_CHAT_SCRIPT_DEFINE(u_blox_lara_r6_init_chat_script, u_blox_lara_r6_init_chat_script_cmds,
2105 abort_matches, modem_cellular_chat_callback_handler, 10);
2106
2107 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_lara_r6_dial_chat_script_cmds,
2108 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
2109 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
2110 "\""CONFIG_MODEM_CELLULAR_APN"\"",
2111 ok_match),
2112 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
2113 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
2114
2115 MODEM_CHAT_SCRIPT_DEFINE(u_blox_lara_r6_dial_chat_script, u_blox_lara_r6_dial_chat_script_cmds,
2116 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
2117
2118 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_lara_r6_periodic_chat_script_cmds,
2119 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2120 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2121 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
2122
2123 MODEM_CHAT_SCRIPT_DEFINE(u_blox_lara_r6_periodic_chat_script,
2124 u_blox_lara_r6_periodic_chat_script_cmds, abort_matches,
2125 modem_cellular_chat_callback_handler, 4);
2126 #endif
2127
2128 #if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800)
2129 MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_init_chat_script_cmds,
2130 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2131 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2132 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2133 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2134 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
2135 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
2136 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0", allow_match),
2137 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
2138 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
2139 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
2140 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
2141 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2142 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2143 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
2144 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2145 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
2146 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2147 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
2148 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2149 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
2150 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2151 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
2152 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2153 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,127", ok_match));
2154
2155 MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_init_chat_script, swir_hl7800_init_chat_script_cmds,
2156 abort_matches, modem_cellular_chat_callback_handler, 10);
2157
2158 MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_dial_chat_script_cmds,
2159 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
2160 "\""CONFIG_MODEM_CELLULAR_APN"\"",
2161 ok_match),
2162 MODEM_CHAT_SCRIPT_CMD_RESP("AT+KCNXCFG=1,\"GPRS\",\""
2163 CONFIG_MODEM_CELLULAR_APN
2164 "\",,,\"IPV4\"",
2165 ok_match),
2166 MODEM_CHAT_SCRIPT_CMD_RESP("AT+WPPP=0", ok_match),
2167 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
2168 MODEM_CHAT_SCRIPT_CMD_RESP("ATD*99***1#", connect_match));
2169
2170 MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_periodic_chat_script_cmds,
2171 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2172 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match));
2173
2174 MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_periodic_chat_script,
2175 swir_hl7800_periodic_chat_script_cmds, abort_matches,
2176 modem_cellular_chat_callback_handler, 4);
2177
2178 MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_dial_chat_script, swir_hl7800_dial_chat_script_cmds,
2179 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
2180 #endif
2181
2182 #if DT_HAS_COMPAT_STATUS_OKAY(telit_me910g1) || DT_HAS_COMPAT_STATUS_OKAY(telit_me310g1)
2183 MODEM_CHAT_SCRIPT_CMDS_DEFINE(telit_mex10g1_init_chat_script_cmds,
2184 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2185 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2186 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2187 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
2188 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
2189 MODEM_CHAT_SCRIPT_CMD_RESP("AT+ICCID", iccid_match),
2190 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2191 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
2192 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2193 /* The Telit me910g1 often has an error trying
2194 * to set the PDP context. The radio must be on to set
2195 * the context, and this step must be successful.
2196 * It is moved to the init script to allow retries.
2197 */
2198 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
2199 "\"" CONFIG_MODEM_CELLULAR_APN "\"",
2200 ok_match),
2201 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
2202 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
2203 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
2204 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
2205 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
2206 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2207 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2208 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
2209 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
2210 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2211 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
2212 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2213 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
2214 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2215 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
2216 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2217 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
2218 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2",
2219 300));
2220
2221 MODEM_CHAT_SCRIPT_DEFINE(telit_mex10g1_init_chat_script, telit_mex10g1_init_chat_script_cmds,
2222 abort_matches, modem_cellular_chat_callback_handler, 10);
2223
2224 MODEM_CHAT_SCRIPT_CMDS_DEFINE(telit_mex10g1_dial_chat_script_cmds,
2225 MODEM_CHAT_SCRIPT_CMD_RESP("AT", ok_match),
2226 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0));
2227
2228 MODEM_CHAT_SCRIPT_DEFINE(telit_mex10g1_dial_chat_script, telit_mex10g1_dial_chat_script_cmds,
2229 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
2230
2231 MODEM_CHAT_SCRIPT_CMDS_DEFINE(telit_mex10g1_periodic_chat_script_cmds,
2232 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
2233 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
2234 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match));
2235
2236 MODEM_CHAT_SCRIPT_DEFINE(telit_mex10g1_periodic_chat_script,
2237 telit_mex10g1_periodic_chat_script_cmds, abort_matches,
2238 modem_cellular_chat_callback_handler, 4);
2239
2240 #endif
2241
2242 #if DT_HAS_COMPAT_STATUS_OKAY(telit_me310g1)
2243 MODEM_CHAT_SCRIPT_CMDS_DEFINE(telit_me310g1_shutdown_chat_script_cmds,
2244 MODEM_CHAT_SCRIPT_CMD_RESP("AT#SHDN", ok_match));
2245
2246 MODEM_CHAT_SCRIPT_DEFINE(telit_me310g1_shutdown_chat_script,
2247 telit_me310g1_shutdown_chat_script_cmds, abort_matches,
2248 modem_cellular_chat_callback_handler, 15);
2249
2250 #endif
2251
2252 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf91_slm)
2253 MODEM_CHAT_SCRIPT_CMDS_DEFINE(nordic_nrf91_slm_init_chat_script_cmds,
2254 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT", allow_match),
2255 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
2256 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
2257 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2258 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
2259 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2260 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
2261 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2262 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
2263 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2264 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
2265 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2266 MODEM_CHAT_SCRIPT_CMD_RESP("AT#XCMUX=1", ok_match));
2267
2268 MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_init_chat_script, nordic_nrf91_slm_init_chat_script_cmds,
2269 abort_matches, modem_cellular_chat_callback_handler, 10);
2270
2271 MODEM_CHAT_SCRIPT_CMDS_DEFINE(nordic_nrf91_slm_dial_chat_script_cmds,
2272 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
2273 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
2274 MODEM_CHAT_SCRIPT_CMD_RESP("AT#XCMUX=2", ok_match));
2275
2276 MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_dial_chat_script, nordic_nrf91_slm_dial_chat_script_cmds,
2277 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
2278
2279 MODEM_CHAT_SCRIPT_CMDS_DEFINE(nordic_nrf91_slm_periodic_chat_script_cmds,
2280 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match));
2281
2282 MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_periodic_chat_script,
2283 nordic_nrf91_slm_periodic_chat_script_cmds, abort_matches,
2284 modem_cellular_chat_callback_handler, 4);
2285 #endif
2286
2287 #if DT_HAS_COMPAT_STATUS_OKAY(sqn_gm02s)
2288 MODEM_CHAT_SCRIPT_CMDS_DEFINE(sqn_gm02s_init_chat_script_cmds,
2289 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
2290 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
2291 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
2292 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
2293 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
2294 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
2295 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2296 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
2297 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2298 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
2299 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2300 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
2301 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
2302 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,127", ok_match));
2303
2304 MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_init_chat_script, sqn_gm02s_init_chat_script_cmds,
2305 abort_matches, modem_cellular_chat_callback_handler, 10);
2306
2307 MODEM_CHAT_SCRIPT_CMDS_DEFINE(sqn_gm02s_dial_chat_script_cmds,
2308 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
2309 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
2310 "\""CONFIG_MODEM_CELLULAR_APN"\"",
2311 ok_match),
2312 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CFUN=1", 10000),
2313 MODEM_CHAT_SCRIPT_CMD_RESP("ATD*99***1#", connect_match));
2314
2315 MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_dial_chat_script, sqn_gm02s_dial_chat_script_cmds,
2316 dial_abort_matches, modem_cellular_chat_callback_handler, 15);
2317
2318 MODEM_CHAT_SCRIPT_CMDS_DEFINE(sqn_gm02s_periodic_chat_script_cmds,
2319 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match));
2320
2321 MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script,
2322 sqn_gm02s_periodic_chat_script_cmds, abort_matches,
2323 modem_cellular_chat_callback_handler, 4);
2324 #endif
2325
2326 #define MODEM_CELLULAR_INST_NAME(name, inst) \
2327 _CONCAT_4(name, _, DT_DRV_COMPAT, inst)
2328
2329 #define MODEM_CELLULAR_DEFINE_USER_PIPE_DATA(inst, name, size) \
2330 MODEM_PIPELINK_DT_INST_DEFINE(inst, name); \
2331 static uint8_t MODEM_CELLULAR_INST_NAME(name, inst)[size] \
2332
2333 #define MODEM_CELLULAR_INIT_USER_PIPE(_inst, _name, _dlci_address) \
2334 { \
2335 .dlci_address = _dlci_address, \
2336 .dlci_receive_buf = MODEM_CELLULAR_INST_NAME(_name, _inst), \
2337 .dlci_receive_buf_size = sizeof(MODEM_CELLULAR_INST_NAME(_name, _inst)), \
2338 .pipelink = MODEM_PIPELINK_DT_INST_GET(_inst, _name), \
2339 }
2340
2341 #define MODEM_CELLULAR_DEFINE_USER_PIPES(inst, ...) \
2342 static struct modem_cellular_user_pipe MODEM_CELLULAR_INST_NAME(user_pipes, inst)[] = { \
2343 __VA_ARGS__ \
2344 }
2345
2346 #define MODEM_CELLULAR_GET_USER_PIPES(inst) \
2347 MODEM_CELLULAR_INST_NAME(user_pipes, inst)
2348
2349 /* Extract the first argument (pipe name) from a pair */
2350 #define MODEM_CELLULAR_GET_PIPE_NAME_ARG(arg1, ...) arg1
2351
2352 /* Extract the second argument (DLCI address) from a pair */
2353 #define MODEM_CELLULAR_GET_DLCI_ADDRESS_ARG(arg1, arg2, ...) arg2
2354
2355 /* Define user pipe data using instance and extracted pipe name */
2356 #define MODEM_CELLULAR_DEFINE_USER_PIPE_DATA_HELPER(_args, inst) \
2357 MODEM_CELLULAR_DEFINE_USER_PIPE_DATA(inst, \
2358 MODEM_CELLULAR_GET_PIPE_NAME_ARG _args, \
2359 CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES)
2360
2361 /* Initialize user pipe using instance, extracted pipe name, and DLCI address */
2362 #define MODEM_CELLULAR_INIT_USER_PIPE_HELPER(_args, inst) \
2363 MODEM_CELLULAR_INIT_USER_PIPE(inst, \
2364 MODEM_CELLULAR_GET_PIPE_NAME_ARG _args, \
2365 MODEM_CELLULAR_GET_DLCI_ADDRESS_ARG _args)
2366
2367 /*
2368 * Define and initialize user pipes dynamically
2369 * Takes an instance and pairs of (pipe name, DLCI address)
2370 */
2371 #define MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, ...) \
2372 FOR_EACH_FIXED_ARG(MODEM_CELLULAR_DEFINE_USER_PIPE_DATA_HELPER, \
2373 (;), inst, __VA_ARGS__); \
2374 MODEM_CELLULAR_DEFINE_USER_PIPES( \
2375 inst, \
2376 FOR_EACH_FIXED_ARG(MODEM_CELLULAR_INIT_USER_PIPE_HELPER, \
2377 (,), inst, __VA_ARGS__) \
2378 );
2379
2380 /* Helper to define modem instance */
2381 #define MODEM_CELLULAR_DEFINE_INSTANCE(inst, power_ms, reset_ms, startup_ms, shutdown_ms, start, \
2382 set_baudrate_script, \
2383 init_script, \
2384 dial_script, \
2385 periodic_script, \
2386 shutdown_script) \
2387 static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \
2388 .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \
2389 .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \
2390 .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \
2391 .power_pulse_duration_ms = (power_ms), \
2392 .reset_pulse_duration_ms = (reset_ms), \
2393 .startup_time_ms = (startup_ms), \
2394 .shutdown_time_ms = (shutdown_ms), \
2395 .autostarts = (start), \
2396 .set_baudrate_chat_script = (set_baudrate_script), \
2397 .init_chat_script = (init_script), \
2398 .dial_chat_script = (dial_script), \
2399 .periodic_chat_script = (periodic_script), \
2400 .shutdown_chat_script = (shutdown_script), \
2401 .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \
2402 .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \
2403 }; \
2404 \
2405 PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \
2406 \
2407 DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \
2408 &MODEM_CELLULAR_INST_NAME(data, inst), \
2409 &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, \
2410 &modem_cellular_api);
2411
2412 #define MODEM_CELLULAR_DEVICE_QUECTEL_BG95(inst) \
2413 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2414 \
2415 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2416 .chat_delimiter = "\r", \
2417 .chat_filter = "\n", \
2418 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2419 }; \
2420 \
2421 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2422 (user_pipe_0, 3), \
2423 (user_pipe_1, 4)) \
2424 \
2425 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 100, 10000, 5000, false, \
2426 NULL, \
2427 &quectel_bg95_init_chat_script, \
2428 &quectel_bg95_dial_chat_script, \
2429 &quectel_bg95_periodic_chat_script, NULL)
2430
2431 #define MODEM_CELLULAR_DEVICE_QUECTEL_EG25_G(inst) \
2432 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2433 \
2434 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2435 .chat_delimiter = "\r", \
2436 .chat_filter = "\n", \
2437 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2438 }; \
2439 \
2440 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2441 (user_pipe_0, 3), \
2442 (user_pipe_1, 4)) \
2443 \
2444 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 500, 15000, 5000, false, \
2445 NULL, \
2446 &quectel_eg25_g_init_chat_script, \
2447 &quectel_eg25_g_dial_chat_script, \
2448 &quectel_eg25_g_periodic_chat_script, NULL)
2449
2450 #define MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080(inst) \
2451 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2452 \
2453 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2454 .chat_delimiter = "\r", \
2455 .chat_filter = "\n", \
2456 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2457 }; \
2458 \
2459 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2460 (user_pipe_0, 3), \
2461 (user_pipe_1, 4)) \
2462 \
2463 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 100, 10000, 5000, false, \
2464 NULL, \
2465 &simcom_sim7080_init_chat_script, \
2466 &simcom_sim7080_dial_chat_script, \
2467 &simcom_sim7080_periodic_chat_script, NULL)
2468
2469 #define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4(inst) \
2470 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2471 \
2472 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2473 .chat_delimiter = "\r", \
2474 .chat_filter = "\n", \
2475 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2476 }; \
2477 \
2478 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2479 (gnss_pipe, 3), \
2480 (user_pipe_0, 4)) \
2481 \
2482 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 100, 10000, 5000, false, \
2483 NULL, \
2484 &u_blox_sara_r4_init_chat_script, \
2485 &u_blox_sara_r4_dial_chat_script, \
2486 &u_blox_sara_r4_periodic_chat_script, NULL)
2487
2488 #define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R5(inst) \
2489 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2490 \
2491 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2492 .chat_delimiter = "\r", \
2493 .chat_filter = "\n", \
2494 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2495 }; \
2496 \
2497 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2498 (gnss_pipe, 4), \
2499 (user_pipe_0, 3)) \
2500 \
2501 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 100, 1500, 13000, true, \
2502 NULL, \
2503 &u_blox_sara_r5_init_chat_script, \
2504 &u_blox_sara_r5_dial_chat_script, \
2505 &u_blox_sara_r5_periodic_chat_script, NULL)
2506
2507 #define MODEM_CELLULAR_DEVICE_U_BLOX_LARA_R6(inst) \
2508 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2509 \
2510 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2511 .chat_delimiter = "\r", \
2512 .chat_filter = "\n", \
2513 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2514 }; \
2515 \
2516 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2517 (gnss_pipe, 3), \
2518 (user_pipe_0, 4)) \
2519 \
2520 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 100, 9000, 5000, false, \
2521 &u_blox_lara_r6_set_baudrate_chat_script, \
2522 &u_blox_lara_r6_init_chat_script, \
2523 &u_blox_lara_r6_dial_chat_script, \
2524 &u_blox_lara_r6_periodic_chat_script, \
2525 NULL)
2526
2527 #define MODEM_CELLULAR_DEVICE_SWIR_HL7800(inst) \
2528 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2529 \
2530 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2531 .chat_delimiter = "\r", \
2532 .chat_filter = "\n", \
2533 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2534 }; \
2535 \
2536 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2537 (user_pipe_0, 3), \
2538 (user_pipe_1, 4)) \
2539 \
2540 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 100, 10000, 5000, false, \
2541 NULL, \
2542 &swir_hl7800_init_chat_script, \
2543 &swir_hl7800_dial_chat_script, \
2544 &swir_hl7800_periodic_chat_script, NULL)
2545
2546 #define MODEM_CELLULAR_DEVICE_TELIT_ME910G1(inst) \
2547 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2548 \
2549 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2550 .chat_delimiter = "\r", \
2551 .chat_filter = "\n", \
2552 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2553 }; \
2554 \
2555 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2556 (user_pipe_0, 3)) \
2557 \
2558 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 5050, 250, 15000, 5000, false, \
2559 NULL, \
2560 &telit_mex10g1_init_chat_script, \
2561 &telit_mex10g1_dial_chat_script, \
2562 &telit_mex10g1_periodic_chat_script, \
2563 NULL)
2564
2565 #define MODEM_CELLULAR_DEVICE_TELIT_ME310G1(inst) \
2566 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2567 \
2568 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2569 .chat_delimiter = "\r", \
2570 .chat_filter = "\n", \
2571 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2572 }; \
2573 \
2574 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2575 (user_pipe_0, 3)) \
2576 \
2577 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 5050, 0 /* unused */, 1000, 15000, false, \
2578 NULL, \
2579 &telit_mex10g1_init_chat_script, \
2580 &telit_mex10g1_dial_chat_script, \
2581 &telit_mex10g1_periodic_chat_script, \
2582 &telit_me310g1_shutdown_chat_script)
2583
2584 #define MODEM_CELLULAR_DEVICE_NORDIC_NRF91_SLM(inst) \
2585 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 1500); \
2586 \
2587 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2588 .chat_delimiter = "\r\n", \
2589 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2590 }; \
2591 \
2592 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2593 (gnss_pipe, 3)) \
2594 \
2595 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 100, 100, 2000, 10000, false, \
2596 NULL, \
2597 &nordic_nrf91_slm_init_chat_script, \
2598 &nordic_nrf91_slm_dial_chat_script, \
2599 &nordic_nrf91_slm_periodic_chat_script, NULL)
2600
2601 #define MODEM_CELLULAR_DEVICE_SQN_GM02S(inst) \
2602 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2603 \
2604 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2605 .chat_delimiter = "\r", \
2606 .chat_filter = "\n", \
2607 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2608 }; \
2609 \
2610 MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2611 (user_pipe_0, 3), \
2612 (user_pipe_1, 4)) \
2613 \
2614 MODEM_CELLULAR_DEFINE_INSTANCE(inst, 1500, 100, 2000, 5000, true, \
2615 NULL, \
2616 &sqn_gm02s_init_chat_script, \
2617 &sqn_gm02s_dial_chat_script, \
2618 &sqn_gm02s_periodic_chat_script, NULL)
2619
2620 #define DT_DRV_COMPAT quectel_bg95
2621 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_BG95)
2622 #undef DT_DRV_COMPAT
2623
2624 #define DT_DRV_COMPAT quectel_eg25_g
2625 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_EG25_G)
2626 #undef DT_DRV_COMPAT
2627
2628 #define DT_DRV_COMPAT simcom_sim7080
2629 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080)
2630 #undef DT_DRV_COMPAT
2631
2632 #define DT_DRV_COMPAT u_blox_sara_r4
2633 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4)
2634 #undef DT_DRV_COMPAT
2635
2636 #define DT_DRV_COMPAT u_blox_sara_r5
2637 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R5)
2638 #undef DT_DRV_COMPAT
2639
2640 #define DT_DRV_COMPAT u_blox_lara_r6
2641 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_U_BLOX_LARA_R6)
2642 #undef DT_DRV_COMPAT
2643
2644 #define DT_DRV_COMPAT swir_hl7800
2645 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SWIR_HL7800)
2646 #undef DT_DRV_COMPAT
2647
2648 #define DT_DRV_COMPAT telit_me910g1
2649 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_TELIT_ME910G1)
2650 #undef DT_DRV_COMPAT
2651
2652 #define DT_DRV_COMPAT telit_me310g1
2653 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_TELIT_ME310G1)
2654 #undef DT_DRV_COMPAT
2655
2656 #define DT_DRV_COMPAT nordic_nrf91_slm
2657 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_NORDIC_NRF91_SLM)
2658 #undef DT_DRV_COMPAT
2659
2660 #define DT_DRV_COMPAT sqn_gm02s
2661 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SQN_GM02S)
2662 #undef DT_DRV_COMPAT
2663