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/modem/chat.h>
11 #include <zephyr/modem/cmux.h>
12 #include <zephyr/modem/pipe.h>
13 #include <zephyr/modem/ppp.h>
14 #include <zephyr/modem/backend/uart.h>
15 #include <zephyr/net/ppp.h>
16 #include <zephyr/pm/device.h>
17 #include <zephyr/sys/atomic.h>
18
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(modem_cellular, CONFIG_MODEM_LOG_LEVEL);
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 enum modem_cellular_state {
26 MODEM_CELLULAR_STATE_IDLE = 0,
27 MODEM_CELLULAR_STATE_RESET_PULSE,
28 MODEM_CELLULAR_STATE_POWER_ON_PULSE,
29 MODEM_CELLULAR_STATE_AWAIT_POWER_ON,
30 MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT,
31 MODEM_CELLULAR_STATE_CONNECT_CMUX,
32 MODEM_CELLULAR_STATE_OPEN_DLCI1,
33 MODEM_CELLULAR_STATE_OPEN_DLCI2,
34 MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT,
35 MODEM_CELLULAR_STATE_AWAIT_REGISTERED,
36 MODEM_CELLULAR_STATE_CARRIER_ON,
37 MODEM_CELLULAR_STATE_INIT_POWER_OFF,
38 MODEM_CELLULAR_STATE_POWER_OFF_PULSE,
39 MODEM_CELLULAR_STATE_AWAIT_POWER_OFF,
40 };
41
42 enum modem_cellular_event {
43 MODEM_CELLULAR_EVENT_RESUME = 0,
44 MODEM_CELLULAR_EVENT_SUSPEND,
45 MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS,
46 MODEM_CELLULAR_EVENT_SCRIPT_FAILED,
47 MODEM_CELLULAR_EVENT_CMUX_CONNECTED,
48 MODEM_CELLULAR_EVENT_DLCI1_OPENED,
49 MODEM_CELLULAR_EVENT_DLCI2_OPENED,
50 MODEM_CELLULAR_EVENT_TIMEOUT,
51 MODEM_CELLULAR_EVENT_REGISTERED,
52 MODEM_CELLULAR_EVENT_DEREGISTERED,
53 MODEM_CELLULAR_EVENT_BUS_OPENED,
54 MODEM_CELLULAR_EVENT_BUS_CLOSED,
55 };
56
57 struct modem_cellular_data {
58 /* UART backend */
59 struct modem_pipe *uart_pipe;
60 struct modem_backend_uart uart_backend;
61 uint8_t uart_backend_receive_buf[512];
62 uint8_t uart_backend_transmit_buf[512];
63
64 /* CMUX */
65 struct modem_cmux cmux;
66 uint8_t cmux_receive_buf[128];
67 uint8_t cmux_transmit_buf[256];
68 struct modem_cmux_dlci dlci1;
69 struct modem_cmux_dlci dlci2;
70 struct modem_pipe *dlci1_pipe;
71 struct modem_pipe *dlci2_pipe;
72 uint8_t dlci1_receive_buf[128];
73 uint8_t dlci2_receive_buf[256];
74
75 /* Modem chat */
76 struct modem_chat chat;
77 uint8_t chat_receive_buf[128];
78 uint8_t chat_delimiter[1];
79 uint8_t chat_filter[1];
80 uint8_t *chat_argv[32];
81
82 /* Status */
83 uint8_t imei[15];
84 uint8_t hwinfo[64];
85 uint8_t registration_status_gsm;
86 uint8_t registration_status_gprs;
87 uint8_t registration_status_lte;
88
89 /* PPP */
90 struct modem_ppp *ppp;
91
92 enum modem_cellular_state state;
93 const struct device *dev;
94 struct k_work_delayable timeout_work;
95
96 /* Power management */
97 struct k_sem suspended_sem;
98
99 /* Event dispatcher */
100 struct k_work event_dispatch_work;
101 uint8_t event_buf[8];
102 struct ring_buf event_rb;
103 struct k_mutex event_rb_lock;
104 };
105
106 struct modem_cellular_config {
107 const struct device *uart;
108 const struct gpio_dt_spec power_gpio;
109 const struct gpio_dt_spec reset_gpio;
110 const uint16_t power_pulse_duration_ms;
111 const uint16_t reset_pulse_duration_ms;
112 const uint16_t startup_time_ms;
113 const uint16_t shutdown_time_ms;
114 const struct modem_chat_script *init_chat_script;
115 const struct modem_chat_script *dial_chat_script;
116 };
117
modem_cellular_state_str(enum modem_cellular_state state)118 static const char *modem_cellular_state_str(enum modem_cellular_state state)
119 {
120 switch (state) {
121 case MODEM_CELLULAR_STATE_IDLE:
122 return "idle";
123 case MODEM_CELLULAR_STATE_RESET_PULSE:
124 return "reset pulse";
125 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
126 return "power pulse";
127 case MODEM_CELLULAR_STATE_AWAIT_POWER_ON:
128 return "await power on";
129 case MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT:
130 return "run init script";
131 case MODEM_CELLULAR_STATE_CONNECT_CMUX:
132 return "connect cmux";
133 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
134 return "open dlci1";
135 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
136 return "open dlci2";
137 case MODEM_CELLULAR_STATE_AWAIT_REGISTERED:
138 return "await registered";
139 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
140 return "run dial script";
141 case MODEM_CELLULAR_STATE_CARRIER_ON:
142 return "carrier on";
143 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
144 return "init power off";
145 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
146 return "power off pulse";
147 case MODEM_CELLULAR_STATE_AWAIT_POWER_OFF:
148 return "await power off";
149 }
150
151 return "";
152 }
153
modem_cellular_event_str(enum modem_cellular_event event)154 static const char *modem_cellular_event_str(enum modem_cellular_event event)
155 {
156 switch (event) {
157 case MODEM_CELLULAR_EVENT_RESUME:
158 return "resume";
159 case MODEM_CELLULAR_EVENT_SUSPEND:
160 return "suspend";
161 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
162 return "script success";
163 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
164 return "script failed";
165 case MODEM_CELLULAR_EVENT_CMUX_CONNECTED:
166 return "cmux connected";
167 case MODEM_CELLULAR_EVENT_DLCI1_OPENED:
168 return "dlci1 opened";
169 case MODEM_CELLULAR_EVENT_DLCI2_OPENED:
170 return "dlci2 opened";
171 case MODEM_CELLULAR_EVENT_TIMEOUT:
172 return "timeout";
173 case MODEM_CELLULAR_EVENT_REGISTERED:
174 return "registered";
175 case MODEM_CELLULAR_EVENT_DEREGISTERED:
176 return "deregistered";
177 case MODEM_CELLULAR_EVENT_BUS_OPENED:
178 return "bus opened";
179 case MODEM_CELLULAR_EVENT_BUS_CLOSED:
180 return "bus closed";
181 }
182
183 return "";
184 }
185
modem_cellular_gpio_is_enabled(const struct gpio_dt_spec * gpio)186 static bool modem_cellular_gpio_is_enabled(const struct gpio_dt_spec *gpio)
187 {
188 return gpio->port != NULL;
189 }
190
191 static void modem_cellular_enter_state(struct modem_cellular_data *data,
192 enum modem_cellular_state state);
193
194 static void modem_cellular_delegate_event(struct modem_cellular_data *data,
195 enum modem_cellular_event evt);
196
197 static void modem_cellular_event_handler(struct modem_cellular_data *data,
198 enum modem_cellular_event evt);
199
modem_cellular_bus_pipe_handler(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)200 static void modem_cellular_bus_pipe_handler(struct modem_pipe *pipe,
201 enum modem_pipe_event event,
202 void *user_data)
203 {
204 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
205
206 switch (event) {
207 case MODEM_PIPE_EVENT_OPENED:
208 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_BUS_OPENED);
209 break;
210
211 case MODEM_PIPE_EVENT_CLOSED:
212 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_BUS_CLOSED);
213 break;
214
215 default:
216 break;
217 }
218 }
219
modem_cellular_dlci1_pipe_handler(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)220 static void modem_cellular_dlci1_pipe_handler(struct modem_pipe *pipe,
221 enum modem_pipe_event event,
222 void *user_data)
223 {
224 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
225
226 switch (event) {
227 case MODEM_PIPE_EVENT_OPENED:
228 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_DLCI1_OPENED);
229 break;
230
231 default:
232 break;
233 }
234 }
235
modem_cellular_dlci2_pipe_handler(struct modem_pipe * pipe,enum modem_pipe_event event,void * user_data)236 static void modem_cellular_dlci2_pipe_handler(struct modem_pipe *pipe,
237 enum modem_pipe_event event,
238 void *user_data)
239 {
240 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
241
242 switch (event) {
243 case MODEM_PIPE_EVENT_OPENED:
244 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_DLCI2_OPENED);
245 break;
246
247 default:
248 break;
249 }
250 }
251
modem_cellular_chat_callback_handler(struct modem_chat * chat,enum modem_chat_script_result result,void * user_data)252 static void modem_cellular_chat_callback_handler(struct modem_chat *chat,
253 enum modem_chat_script_result result,
254 void *user_data)
255 {
256 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
257
258 if (result == MODEM_CHAT_SCRIPT_RESULT_SUCCESS) {
259 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS);
260 } else {
261 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_SCRIPT_FAILED);
262 }
263 }
264
modem_cellular_chat_on_imei(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)265 static void modem_cellular_chat_on_imei(struct modem_chat *chat, char **argv, uint16_t argc,
266 void *user_data)
267 {
268 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
269
270 if (argc != 2) {
271 return;
272 }
273
274 if (strlen(argv[1]) != 15) {
275 return;
276 }
277
278 for (uint8_t i = 0; i < 15; i++) {
279 data->imei[i] = argv[1][i] - '0';
280 }
281 }
282
modem_cellular_chat_on_cgmm(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)283 static void modem_cellular_chat_on_cgmm(struct modem_chat *chat, char **argv, uint16_t argc,
284 void *user_data)
285 {
286 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
287
288 if (argc != 2) {
289 return;
290 }
291
292 strncpy(data->hwinfo, argv[1], sizeof(data->hwinfo) - 1);
293 }
294
modem_cellular_is_registered(struct modem_cellular_data * data)295 static bool modem_cellular_is_registered(struct modem_cellular_data *data)
296 {
297 return (data->registration_status_gsm == 1)
298 || (data->registration_status_gsm == 5)
299 || (data->registration_status_gprs == 1)
300 || (data->registration_status_gprs == 5)
301 || (data->registration_status_lte == 1)
302 || (data->registration_status_lte == 5);
303 }
304
modem_cellular_chat_on_cxreg(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)305 static void modem_cellular_chat_on_cxreg(struct modem_chat *chat, char **argv, uint16_t argc,
306 void *user_data)
307 {
308 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
309 uint8_t registration_status;
310 bool is_registered;
311
312 is_registered = modem_cellular_is_registered(data);
313
314 if (argc == 2) {
315 registration_status = atoi(argv[1]);
316 } else if (argc == 3) {
317 registration_status = atoi(argv[2]);
318 } else {
319 return;
320 }
321
322 if (strcmp(argv[0], "+CREG: ") == 0) {
323 data->registration_status_gsm = registration_status;
324 } else if (strcmp(argv[0], "+CGREG: ") == 0) {
325 data->registration_status_gprs = registration_status;
326 } else {
327 data->registration_status_lte = registration_status;
328 }
329
330 if (modem_cellular_is_registered(data)) {
331 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_REGISTERED);
332 } else {
333 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_DEREGISTERED);
334 }
335 }
336
337 MODEM_CHAT_MATCH_DEFINE(ok_match, "OK", "", NULL);
338 MODEM_CHAT_MATCHES_DEFINE(allow_match,
339 MODEM_CHAT_MATCH("OK", "", NULL),
340 MODEM_CHAT_MATCH("ERROR", "", NULL));
341
342 MODEM_CHAT_MATCH_DEFINE(imei_match, "", "", modem_cellular_chat_on_imei);
343 MODEM_CHAT_MATCH_DEFINE(cgmm_match, "", "", modem_cellular_chat_on_cgmm);
344
345 MODEM_CHAT_MATCHES_DEFINE(unsol_matches,
346 MODEM_CHAT_MATCH("+CREG: ", ",", modem_cellular_chat_on_cxreg),
347 MODEM_CHAT_MATCH("+CEREG: ", ",", modem_cellular_chat_on_cxreg),
348 MODEM_CHAT_MATCH("+CGREG: ", ",", modem_cellular_chat_on_cxreg));
349
350 MODEM_CHAT_MATCHES_DEFINE(abort_matches, MODEM_CHAT_MATCH("ERROR", "", NULL));
351
352 MODEM_CHAT_MATCHES_DEFINE(dial_abort_matches,
353 MODEM_CHAT_MATCH("ERROR", "", NULL),
354 MODEM_CHAT_MATCH("BUSY", "", NULL),
355 MODEM_CHAT_MATCH("NO ANSWER", "", NULL),
356 MODEM_CHAT_MATCH("NO CARRIER", "", NULL),
357 MODEM_CHAT_MATCH("NO DIALTONE", "", NULL));
358
modem_cellular_log_state_changed(enum modem_cellular_state last_state,enum modem_cellular_state new_state)359 static void modem_cellular_log_state_changed(enum modem_cellular_state last_state,
360 enum modem_cellular_state new_state)
361 {
362 LOG_INF("switch from %s to %s", modem_cellular_state_str(last_state),
363 modem_cellular_state_str(new_state));
364 }
365
modem_cellular_log_event(enum modem_cellular_event evt)366 static void modem_cellular_log_event(enum modem_cellular_event evt)
367 {
368 LOG_INF("event %s", modem_cellular_event_str(evt));
369 }
370
modem_cellular_start_timer(struct modem_cellular_data * data,k_timeout_t timeout)371 static void modem_cellular_start_timer(struct modem_cellular_data *data, k_timeout_t timeout)
372 {
373 k_work_schedule(&data->timeout_work, timeout);
374 }
375
modem_cellular_stop_timer(struct modem_cellular_data * data)376 static void modem_cellular_stop_timer(struct modem_cellular_data *data)
377 {
378 k_work_cancel_delayable(&data->timeout_work);
379 }
380
modem_cellular_timeout_handler(struct k_work * item)381 static void modem_cellular_timeout_handler(struct k_work *item)
382 {
383 struct k_work_delayable *dwork = k_work_delayable_from_work(item);
384 struct modem_cellular_data *data =
385 CONTAINER_OF(dwork, struct modem_cellular_data, timeout_work);
386
387 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_TIMEOUT);
388 }
389
modem_cellular_event_dispatch_handler(struct k_work * item)390 static void modem_cellular_event_dispatch_handler(struct k_work *item)
391 {
392 struct modem_cellular_data *data =
393 CONTAINER_OF(item, struct modem_cellular_data, event_dispatch_work);
394
395 uint8_t events[sizeof(data->event_buf)];
396 uint8_t events_cnt;
397
398 k_mutex_lock(&data->event_rb_lock, K_FOREVER);
399
400 events_cnt = (uint8_t)ring_buf_get(&data->event_rb, events, sizeof(data->event_buf));
401
402 k_mutex_unlock(&data->event_rb_lock);
403
404 for (uint8_t i = 0; i < events_cnt; i++) {
405 modem_cellular_event_handler(data, (enum modem_cellular_event)events[i]);
406 }
407 }
408
modem_cellular_delegate_event(struct modem_cellular_data * data,enum modem_cellular_event evt)409 static void modem_cellular_delegate_event(struct modem_cellular_data *data,
410 enum modem_cellular_event evt)
411 {
412 k_mutex_lock(&data->event_rb_lock, K_FOREVER);
413 ring_buf_put(&data->event_rb, (uint8_t *)&evt, 1);
414 k_mutex_unlock(&data->event_rb_lock);
415 k_work_submit(&data->event_dispatch_work);
416 }
417
modem_cellular_on_idle_state_enter(struct modem_cellular_data * data)418 static int modem_cellular_on_idle_state_enter(struct modem_cellular_data *data)
419 {
420 const struct modem_cellular_config *config =
421 (const struct modem_cellular_config *)data->dev->config;
422
423 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
424 gpio_pin_set_dt(&config->reset_gpio, 1);
425 }
426
427 modem_chat_release(&data->chat);
428 modem_ppp_release(data->ppp);
429 modem_cmux_release(&data->cmux);
430 modem_pipe_close_async(data->uart_pipe);
431 k_sem_give(&data->suspended_sem);
432 return 0;
433 }
434
modem_cellular_idle_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)435 static void modem_cellular_idle_event_handler(struct modem_cellular_data *data,
436 enum modem_cellular_event evt)
437 {
438 const struct modem_cellular_config *config =
439 (const struct modem_cellular_config *)data->dev->config;
440
441 switch (evt) {
442 case MODEM_CELLULAR_EVENT_RESUME:
443 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
444 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_POWER_ON_PULSE);
445 break;
446 }
447
448 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
449 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
450 break;
451 }
452
453 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT);
454 break;
455
456 case MODEM_CELLULAR_EVENT_SUSPEND:
457 k_sem_give(&data->suspended_sem);
458 break;
459
460 default:
461 break;
462 }
463 }
464
modem_cellular_on_idle_state_leave(struct modem_cellular_data * data)465 static int modem_cellular_on_idle_state_leave(struct modem_cellular_data *data)
466 {
467 const struct modem_cellular_config *config =
468 (const struct modem_cellular_config *)data->dev->config;
469
470 k_sem_take(&data->suspended_sem, K_NO_WAIT);
471
472 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
473 gpio_pin_set_dt(&config->reset_gpio, 0);
474 }
475
476 return 0;
477 }
478
modem_cellular_on_reset_pulse_state_enter(struct modem_cellular_data * data)479 static int modem_cellular_on_reset_pulse_state_enter(struct modem_cellular_data *data)
480 {
481 const struct modem_cellular_config *config =
482 (const struct modem_cellular_config *)data->dev->config;
483
484 gpio_pin_set_dt(&config->reset_gpio, 1);
485 modem_cellular_start_timer(data, K_MSEC(config->reset_pulse_duration_ms));
486 return 0;
487 }
488
modem_cellular_reset_pulse_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)489 static void modem_cellular_reset_pulse_event_handler(struct modem_cellular_data *data,
490 enum modem_cellular_event evt)
491 {
492 switch (evt) {
493 case MODEM_CELLULAR_EVENT_TIMEOUT:
494 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
495 break;
496
497 case MODEM_CELLULAR_EVENT_SUSPEND:
498 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
499 break;
500
501 default:
502 break;
503 }
504 }
505
modem_cellular_on_reset_pulse_state_leave(struct modem_cellular_data * data)506 static int modem_cellular_on_reset_pulse_state_leave(struct modem_cellular_data *data)
507 {
508 const struct modem_cellular_config *config =
509 (const struct modem_cellular_config *)data->dev->config;
510
511 gpio_pin_set_dt(&config->reset_gpio, 0);
512 modem_cellular_stop_timer(data);
513 return 0;
514 }
515
modem_cellular_on_power_on_pulse_state_enter(struct modem_cellular_data * data)516 static int modem_cellular_on_power_on_pulse_state_enter(struct modem_cellular_data *data)
517 {
518 const struct modem_cellular_config *config =
519 (const struct modem_cellular_config *)data->dev->config;
520
521 gpio_pin_set_dt(&config->power_gpio, 1);
522 modem_cellular_start_timer(data, K_MSEC(config->power_pulse_duration_ms));
523 return 0;
524 }
525
modem_cellular_power_on_pulse_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)526 static void modem_cellular_power_on_pulse_event_handler(struct modem_cellular_data *data,
527 enum modem_cellular_event evt)
528 {
529 switch (evt) {
530 case MODEM_CELLULAR_EVENT_TIMEOUT:
531 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
532 break;
533
534 case MODEM_CELLULAR_EVENT_SUSPEND:
535 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
536 break;
537
538 default:
539 break;
540 }
541 }
542
modem_cellular_on_power_on_pulse_state_leave(struct modem_cellular_data * data)543 static int modem_cellular_on_power_on_pulse_state_leave(struct modem_cellular_data *data)
544 {
545 const struct modem_cellular_config *config =
546 (const struct modem_cellular_config *)data->dev->config;
547
548 gpio_pin_set_dt(&config->power_gpio, 0);
549 modem_cellular_stop_timer(data);
550 return 0;
551 }
552
modem_cellular_on_await_power_on_state_enter(struct modem_cellular_data * data)553 static int modem_cellular_on_await_power_on_state_enter(struct modem_cellular_data *data)
554 {
555 const struct modem_cellular_config *config =
556 (const struct modem_cellular_config *)data->dev->config;
557
558 modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
559 return 0;
560 }
561
modem_cellular_await_power_on_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)562 static void modem_cellular_await_power_on_event_handler(struct modem_cellular_data *data,
563 enum modem_cellular_event evt)
564 {
565 switch (evt) {
566 case MODEM_CELLULAR_EVENT_TIMEOUT:
567 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT);
568 break;
569
570 case MODEM_CELLULAR_EVENT_SUSPEND:
571 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
572 break;
573
574 default:
575 break;
576 }
577 }
578
modem_cellular_on_run_init_script_state_enter(struct modem_cellular_data * data)579 static int modem_cellular_on_run_init_script_state_enter(struct modem_cellular_data *data)
580 {
581 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
582 return modem_pipe_open_async(data->uart_pipe);
583 }
584
modem_cellular_run_init_script_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)585 static void modem_cellular_run_init_script_event_handler(struct modem_cellular_data *data,
586 enum modem_cellular_event evt)
587 {
588 const struct modem_cellular_config *config =
589 (const struct modem_cellular_config *)data->dev->config;
590
591 switch (evt) {
592 case MODEM_CELLULAR_EVENT_BUS_OPENED:
593 modem_chat_attach(&data->chat, data->uart_pipe);
594 modem_chat_run_script_async(&data->chat, config->init_chat_script);
595 break;
596
597 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
598 net_if_set_link_addr(modem_ppp_get_iface(data->ppp), data->imei,
599 ARRAY_SIZE(data->imei), NET_LINK_UNKNOWN);
600
601 modem_chat_release(&data->chat);
602 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
603 modem_pipe_close_async(data->uart_pipe);
604 break;
605
606 case MODEM_CELLULAR_EVENT_BUS_CLOSED:
607 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CONNECT_CMUX);
608 break;
609
610 case MODEM_CELLULAR_EVENT_SUSPEND:
611 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
612 break;
613
614 case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
615 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
616 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_POWER_ON_PULSE);
617 break;
618 }
619
620 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
621 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
622 break;
623 }
624
625 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
626 break;
627
628 default:
629 break;
630 }
631 }
632
modem_cellular_on_connect_cmux_state_enter(struct modem_cellular_data * data)633 static int modem_cellular_on_connect_cmux_state_enter(struct modem_cellular_data *data)
634 {
635 /*
636 * Allow modem to switch bus into CMUX mode. Some modems disable UART RX while
637 * switching, resulting in UART RX errors as bus is no longer pulled up by modem.
638 */
639 modem_cellular_start_timer(data, K_MSEC(100));
640 return 0;
641 }
642
modem_cellular_connect_cmux_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)643 static void modem_cellular_connect_cmux_event_handler(struct modem_cellular_data *data,
644 enum modem_cellular_event evt)
645 {
646 switch (evt) {
647 case MODEM_CELLULAR_EVENT_TIMEOUT:
648 modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
649 modem_pipe_open_async(data->uart_pipe);
650 break;
651
652 case MODEM_CELLULAR_EVENT_BUS_OPENED:
653 modem_cmux_attach(&data->cmux, data->uart_pipe);
654 modem_cmux_connect_async(&data->cmux);
655 break;
656
657 case MODEM_CELLULAR_EVENT_CMUX_CONNECTED:
658 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_OPEN_DLCI1);
659 break;
660
661 case MODEM_CELLULAR_EVENT_SUSPEND:
662 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
663 break;
664
665 default:
666 break;
667 }
668 }
669
modem_cellular_on_open_dlci1_state_enter(struct modem_cellular_data * data)670 static int modem_cellular_on_open_dlci1_state_enter(struct modem_cellular_data *data)
671 {
672 modem_pipe_attach(data->dlci1_pipe, modem_cellular_dlci1_pipe_handler, data);
673 return modem_pipe_open_async(data->dlci1_pipe);
674 }
675
modem_cellular_open_dlci1_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)676 static void modem_cellular_open_dlci1_event_handler(struct modem_cellular_data *data,
677 enum modem_cellular_event evt)
678 {
679 switch (evt) {
680 case MODEM_CELLULAR_EVENT_DLCI1_OPENED:
681 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_OPEN_DLCI2);
682 break;
683
684 case MODEM_CELLULAR_EVENT_SUSPEND:
685 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
686 break;
687
688 default:
689 break;
690 }
691 }
692
modem_cellular_on_open_dlci1_state_leave(struct modem_cellular_data * data)693 static int modem_cellular_on_open_dlci1_state_leave(struct modem_cellular_data *data)
694 {
695 modem_pipe_release(data->dlci1_pipe);
696 return 0;
697 }
698
modem_cellular_on_open_dlci2_state_enter(struct modem_cellular_data * data)699 static int modem_cellular_on_open_dlci2_state_enter(struct modem_cellular_data *data)
700 {
701 modem_pipe_attach(data->dlci2_pipe, modem_cellular_dlci2_pipe_handler, data);
702 return modem_pipe_open_async(data->dlci2_pipe);
703 }
704
modem_cellular_open_dlci2_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)705 static void modem_cellular_open_dlci2_event_handler(struct modem_cellular_data *data,
706 enum modem_cellular_event evt)
707 {
708 switch (evt) {
709 case MODEM_CELLULAR_EVENT_DLCI2_OPENED:
710 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
711 break;
712
713 case MODEM_CELLULAR_EVENT_SUSPEND:
714 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
715 break;
716
717 default:
718 break;
719 }
720 }
721
modem_cellular_on_open_dlci2_state_leave(struct modem_cellular_data * data)722 static int modem_cellular_on_open_dlci2_state_leave(struct modem_cellular_data *data)
723 {
724 modem_pipe_release(data->dlci2_pipe);
725 return 0;
726 }
727
modem_cellular_on_run_dial_script_state_enter(struct modem_cellular_data * data)728 static int modem_cellular_on_run_dial_script_state_enter(struct modem_cellular_data *data)
729 {
730 /* Allow modem time to enter command mode before running dial script */
731 modem_cellular_start_timer(data, K_MSEC(100));
732 return 0;
733 }
734
modem_cellular_run_dial_script_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)735 static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_data *data,
736 enum modem_cellular_event evt)
737 {
738 const struct modem_cellular_config *config =
739 (const struct modem_cellular_config *)data->dev->config;
740
741 switch (evt) {
742 case MODEM_CELLULAR_EVENT_TIMEOUT:
743 modem_chat_attach(&data->chat, data->dlci1_pipe);
744 modem_chat_run_script_async(&data->chat, config->dial_chat_script);
745 break;
746
747 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
748 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_REGISTERED);
749 break;
750
751 case MODEM_CELLULAR_EVENT_SUSPEND:
752 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
753 break;
754
755 default:
756 break;
757 }
758 }
759
modem_cellular_on_run_dial_script_state_leave(struct modem_cellular_data * data)760 static int modem_cellular_on_run_dial_script_state_leave(struct modem_cellular_data *data)
761 {
762 modem_chat_release(&data->chat);
763 return 0;
764 }
765
modem_cellular_on_await_registered_state_enter(struct modem_cellular_data * data)766 static int modem_cellular_on_await_registered_state_enter(struct modem_cellular_data *data)
767 {
768 if (modem_ppp_attach(data->ppp, data->dlci1_pipe) < 0) {
769 return -EAGAIN;
770 }
771
772 return modem_chat_attach(&data->chat, data->dlci2_pipe);
773 }
774
modem_cellular_await_registered_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)775 static void modem_cellular_await_registered_event_handler(struct modem_cellular_data *data,
776 enum modem_cellular_event evt)
777 {
778 switch (evt) {
779 case MODEM_CELLULAR_EVENT_REGISTERED:
780 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CARRIER_ON);
781 break;
782
783 case MODEM_CELLULAR_EVENT_SUSPEND:
784 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
785 break;
786
787 default:
788 break;
789 }
790 }
791
modem_cellular_on_carrier_on_state_enter(struct modem_cellular_data * data)792 static int modem_cellular_on_carrier_on_state_enter(struct modem_cellular_data *data)
793 {
794 net_if_carrier_on(modem_ppp_get_iface(data->ppp));
795 return 0;
796 }
797
modem_cellular_carrier_on_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)798 static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *data,
799 enum modem_cellular_event evt)
800 {
801 switch (evt) {
802 case MODEM_CELLULAR_EVENT_DEREGISTERED:
803 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
804 break;
805
806 case MODEM_CELLULAR_EVENT_SUSPEND:
807 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
808 break;
809
810 default:
811 break;
812 }
813 }
814
modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data * data)815 static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data *data)
816 {
817 net_if_carrier_off(modem_ppp_get_iface(data->ppp));
818 modem_chat_release(&data->chat);
819 modem_ppp_release(data->ppp);
820 return 0;
821 }
822
modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data * data)823 static int modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data *data)
824 {
825 modem_pipe_close_async(data->uart_pipe);
826 modem_cellular_start_timer(data, K_MSEC(2000));
827 return 0;
828 }
829
modem_cellular_init_power_off_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)830 static void modem_cellular_init_power_off_event_handler(struct modem_cellular_data *data,
831 enum modem_cellular_event evt)
832 {
833 const struct modem_cellular_config *config =
834 (const struct modem_cellular_config *)data->dev->config;
835
836 switch (evt) {
837 case MODEM_CELLULAR_EVENT_TIMEOUT:
838 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
839 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_POWER_OFF_PULSE);
840 break;
841 }
842
843 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
844 break;
845
846 default:
847 break;
848 }
849 }
850
modem_cellular_on_init_power_off_state_leave(struct modem_cellular_data * data)851 static int modem_cellular_on_init_power_off_state_leave(struct modem_cellular_data *data)
852 {
853 modem_chat_release(&data->chat);
854 modem_ppp_release(data->ppp);
855 return 0;
856 }
857
modem_cellular_on_power_off_pulse_state_enter(struct modem_cellular_data * data)858 static int modem_cellular_on_power_off_pulse_state_enter(struct modem_cellular_data *data)
859 {
860 const struct modem_cellular_config *config =
861 (const struct modem_cellular_config *)data->dev->config;
862
863 gpio_pin_set_dt(&config->power_gpio, 1);
864 modem_cellular_start_timer(data, K_MSEC(config->power_pulse_duration_ms));
865 return 0;
866 }
867
modem_cellular_power_off_pulse_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)868 static void modem_cellular_power_off_pulse_event_handler(struct modem_cellular_data *data,
869 enum modem_cellular_event evt)
870 {
871 switch (evt) {
872 case MODEM_CELLULAR_EVENT_TIMEOUT:
873 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_OFF);
874 break;
875
876 default:
877 break;
878 }
879 }
880
modem_cellular_on_power_off_pulse_state_leave(struct modem_cellular_data * data)881 static int modem_cellular_on_power_off_pulse_state_leave(struct modem_cellular_data *data)
882 {
883 const struct modem_cellular_config *config =
884 (const struct modem_cellular_config *)data->dev->config;
885
886 gpio_pin_set_dt(&config->power_gpio, 0);
887 modem_cellular_stop_timer(data);
888 return 0;
889 }
890
modem_cellular_on_await_power_off_state_enter(struct modem_cellular_data * data)891 static int modem_cellular_on_await_power_off_state_enter(struct modem_cellular_data *data)
892 {
893 const struct modem_cellular_config *config =
894 (const struct modem_cellular_config *)data->dev->config;
895
896 modem_cellular_start_timer(data, K_MSEC(config->shutdown_time_ms));
897 return 0;
898 }
899
modem_cellular_await_power_off_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)900 static void modem_cellular_await_power_off_event_handler(struct modem_cellular_data *data,
901 enum modem_cellular_event evt)
902 {
903 switch (evt) {
904 case MODEM_CELLULAR_EVENT_TIMEOUT:
905 modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_IDLE);
906 break;
907
908 default:
909 break;
910 }
911 }
912
modem_cellular_on_state_enter(struct modem_cellular_data * data)913 static int modem_cellular_on_state_enter(struct modem_cellular_data *data)
914 {
915 int ret;
916
917 switch (data->state) {
918 case MODEM_CELLULAR_STATE_IDLE:
919 ret = modem_cellular_on_idle_state_enter(data);
920 break;
921
922 case MODEM_CELLULAR_STATE_RESET_PULSE:
923 ret = modem_cellular_on_reset_pulse_state_enter(data);
924 break;
925
926 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
927 ret = modem_cellular_on_power_on_pulse_state_enter(data);
928 break;
929
930 case MODEM_CELLULAR_STATE_AWAIT_POWER_ON:
931 ret = modem_cellular_on_await_power_on_state_enter(data);
932 break;
933
934 case MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT:
935 ret = modem_cellular_on_run_init_script_state_enter(data);
936 break;
937
938 case MODEM_CELLULAR_STATE_CONNECT_CMUX:
939 ret = modem_cellular_on_connect_cmux_state_enter(data);
940 break;
941
942 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
943 ret = modem_cellular_on_open_dlci1_state_enter(data);
944 break;
945
946 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
947 ret = modem_cellular_on_open_dlci2_state_enter(data);
948 break;
949
950 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
951 ret = modem_cellular_on_run_dial_script_state_enter(data);
952 break;
953
954 case MODEM_CELLULAR_STATE_AWAIT_REGISTERED:
955 ret = modem_cellular_on_await_registered_state_enter(data);
956 break;
957
958 case MODEM_CELLULAR_STATE_CARRIER_ON:
959 ret = modem_cellular_on_carrier_on_state_enter(data);
960 break;
961
962 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
963 ret = modem_cellular_on_init_power_off_state_enter(data);
964 break;
965
966 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
967 ret = modem_cellular_on_power_off_pulse_state_enter(data);
968 break;
969
970 case MODEM_CELLULAR_STATE_AWAIT_POWER_OFF:
971 ret = modem_cellular_on_await_power_off_state_enter(data);
972 break;
973
974 default:
975 ret = 0;
976 break;
977 }
978
979 return ret;
980 }
981
modem_cellular_on_state_leave(struct modem_cellular_data * data)982 static int modem_cellular_on_state_leave(struct modem_cellular_data *data)
983 {
984 int ret;
985
986 switch (data->state) {
987 case MODEM_CELLULAR_STATE_IDLE:
988 ret = modem_cellular_on_idle_state_leave(data);
989 break;
990
991 case MODEM_CELLULAR_STATE_RESET_PULSE:
992 ret = modem_cellular_on_reset_pulse_state_leave(data);
993 break;
994
995 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
996 ret = modem_cellular_on_power_on_pulse_state_leave(data);
997 break;
998
999 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
1000 ret = modem_cellular_on_open_dlci1_state_leave(data);
1001 break;
1002
1003 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
1004 ret = modem_cellular_on_open_dlci2_state_leave(data);
1005 break;
1006
1007 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
1008 ret = modem_cellular_on_run_dial_script_state_leave(data);
1009 break;
1010
1011 case MODEM_CELLULAR_STATE_CARRIER_ON:
1012 ret = modem_cellular_on_carrier_on_state_leave(data);
1013 break;
1014
1015 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
1016 ret = modem_cellular_on_init_power_off_state_leave(data);
1017 break;
1018
1019 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
1020 ret = modem_cellular_on_power_off_pulse_state_leave(data);
1021 break;
1022
1023 default:
1024 ret = 0;
1025 break;
1026 }
1027
1028 return ret;
1029 }
1030
modem_cellular_enter_state(struct modem_cellular_data * data,enum modem_cellular_state state)1031 static void modem_cellular_enter_state(struct modem_cellular_data *data,
1032 enum modem_cellular_state state)
1033 {
1034 int ret;
1035
1036 ret = modem_cellular_on_state_leave(data);
1037
1038 if (ret < 0) {
1039 LOG_WRN("failed to leave state, error: %i", ret);
1040
1041 return;
1042 }
1043
1044 data->state = state;
1045 ret = modem_cellular_on_state_enter(data);
1046
1047 if (ret < 0) {
1048 LOG_WRN("failed to enter state error: %i", ret);
1049 }
1050 }
1051
modem_cellular_event_handler(struct modem_cellular_data * data,enum modem_cellular_event evt)1052 static void modem_cellular_event_handler(struct modem_cellular_data *data,
1053 enum modem_cellular_event evt)
1054 {
1055 enum modem_cellular_state state;
1056
1057 state = data->state;
1058
1059 modem_cellular_log_event(evt);
1060
1061 switch (data->state) {
1062 case MODEM_CELLULAR_STATE_IDLE:
1063 modem_cellular_idle_event_handler(data, evt);
1064 break;
1065
1066 case MODEM_CELLULAR_STATE_RESET_PULSE:
1067 modem_cellular_reset_pulse_event_handler(data, evt);
1068 break;
1069
1070 case MODEM_CELLULAR_STATE_POWER_ON_PULSE:
1071 modem_cellular_power_on_pulse_event_handler(data, evt);
1072 break;
1073
1074 case MODEM_CELLULAR_STATE_AWAIT_POWER_ON:
1075 modem_cellular_await_power_on_event_handler(data, evt);
1076 break;
1077
1078 case MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT:
1079 modem_cellular_run_init_script_event_handler(data, evt);
1080 break;
1081
1082 case MODEM_CELLULAR_STATE_CONNECT_CMUX:
1083 modem_cellular_connect_cmux_event_handler(data, evt);
1084 break;
1085
1086 case MODEM_CELLULAR_STATE_OPEN_DLCI1:
1087 modem_cellular_open_dlci1_event_handler(data, evt);
1088 break;
1089
1090 case MODEM_CELLULAR_STATE_OPEN_DLCI2:
1091 modem_cellular_open_dlci2_event_handler(data, evt);
1092 break;
1093
1094 case MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT:
1095 modem_cellular_run_dial_script_event_handler(data, evt);
1096 break;
1097
1098 case MODEM_CELLULAR_STATE_AWAIT_REGISTERED:
1099 modem_cellular_await_registered_event_handler(data, evt);
1100 break;
1101
1102 case MODEM_CELLULAR_STATE_CARRIER_ON:
1103 modem_cellular_carrier_on_event_handler(data, evt);
1104 break;
1105
1106 case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
1107 modem_cellular_init_power_off_event_handler(data, evt);
1108 break;
1109
1110 case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
1111 modem_cellular_power_off_pulse_event_handler(data, evt);
1112 break;
1113
1114 case MODEM_CELLULAR_STATE_AWAIT_POWER_OFF:
1115 modem_cellular_await_power_off_event_handler(data, evt);
1116 break;
1117 }
1118
1119 if (state != data->state) {
1120 modem_cellular_log_state_changed(state, data->state);
1121 }
1122 }
1123
modem_cellular_cmux_handler(struct modem_cmux * cmux,enum modem_cmux_event event,void * user_data)1124 static void modem_cellular_cmux_handler(struct modem_cmux *cmux, enum modem_cmux_event event,
1125 void *user_data)
1126 {
1127 struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
1128
1129 switch (event) {
1130 case MODEM_CMUX_EVENT_CONNECTED:
1131 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_CMUX_CONNECTED);
1132 break;
1133
1134 default:
1135 break;
1136 }
1137 }
1138
1139 #ifdef CONFIG_PM_DEVICE
modem_cellular_pm_action(const struct device * dev,enum pm_device_action action)1140 static int modem_cellular_pm_action(const struct device *dev, enum pm_device_action action)
1141 {
1142 struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
1143 int ret;
1144
1145 switch (action) {
1146 case PM_DEVICE_ACTION_RESUME:
1147 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
1148 ret = 0;
1149 break;
1150
1151 case PM_DEVICE_ACTION_SUSPEND:
1152 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_SUSPEND);
1153 ret = k_sem_take(&data->suspended_sem, K_SECONDS(30));
1154 break;
1155
1156 default:
1157 ret = -ENOTSUP;
1158 break;
1159 }
1160
1161 return ret;
1162 }
1163 #endif /* CONFIG_PM_DEVICE */
1164
modem_cellular_init(const struct device * dev)1165 static int modem_cellular_init(const struct device *dev)
1166 {
1167 struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
1168 struct modem_cellular_config *config = (struct modem_cellular_config *)dev->config;
1169
1170 data->dev = dev;
1171
1172 k_work_init_delayable(&data->timeout_work, modem_cellular_timeout_handler);
1173
1174 k_work_init(&data->event_dispatch_work, modem_cellular_event_dispatch_handler);
1175 ring_buf_init(&data->event_rb, sizeof(data->event_buf), data->event_buf);
1176
1177 k_sem_init(&data->suspended_sem, 0, 1);
1178
1179 if (modem_cellular_gpio_is_enabled(&config->power_gpio)) {
1180 gpio_pin_configure_dt(&config->power_gpio, GPIO_OUTPUT_INACTIVE);
1181 }
1182
1183 if (modem_cellular_gpio_is_enabled(&config->reset_gpio)) {
1184 gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE);
1185 }
1186
1187 {
1188 const struct modem_backend_uart_config uart_backend_config = {
1189 .uart = config->uart,
1190 .receive_buf = data->uart_backend_receive_buf,
1191 .receive_buf_size = ARRAY_SIZE(data->uart_backend_receive_buf),
1192 .transmit_buf = data->uart_backend_transmit_buf,
1193 .transmit_buf_size = ARRAY_SIZE(data->uart_backend_transmit_buf),
1194 };
1195
1196 data->uart_pipe = modem_backend_uart_init(&data->uart_backend,
1197 &uart_backend_config);
1198 }
1199
1200 {
1201 const struct modem_cmux_config cmux_config = {
1202 .callback = modem_cellular_cmux_handler,
1203 .user_data = data,
1204 .receive_buf = data->cmux_receive_buf,
1205 .receive_buf_size = ARRAY_SIZE(data->cmux_receive_buf),
1206 .transmit_buf = data->cmux_transmit_buf,
1207 .transmit_buf_size = ARRAY_SIZE(data->cmux_transmit_buf),
1208 };
1209
1210 modem_cmux_init(&data->cmux, &cmux_config);
1211 }
1212
1213 {
1214 const struct modem_cmux_dlci_config dlci1_config = {
1215 .dlci_address = 1,
1216 .receive_buf = data->dlci1_receive_buf,
1217 .receive_buf_size = ARRAY_SIZE(data->dlci1_receive_buf),
1218 };
1219
1220 data->dlci1_pipe = modem_cmux_dlci_init(&data->cmux, &data->dlci1,
1221 &dlci1_config);
1222 }
1223
1224 {
1225 const struct modem_cmux_dlci_config dlci2_config = {
1226 .dlci_address = 2,
1227 .receive_buf = data->dlci2_receive_buf,
1228 .receive_buf_size = ARRAY_SIZE(data->dlci2_receive_buf),
1229 };
1230
1231 data->dlci2_pipe = modem_cmux_dlci_init(&data->cmux, &data->dlci2,
1232 &dlci2_config);
1233 }
1234
1235 {
1236 const struct modem_chat_config chat_config = {
1237 .user_data = data,
1238 .receive_buf = data->chat_receive_buf,
1239 .receive_buf_size = ARRAY_SIZE(data->chat_receive_buf),
1240 .delimiter = data->chat_delimiter,
1241 .delimiter_size = ARRAY_SIZE(data->chat_delimiter),
1242 .filter = data->chat_filter,
1243 .filter_size = ARRAY_SIZE(data->chat_filter),
1244 .argv = data->chat_argv,
1245 .argv_size = ARRAY_SIZE(data->chat_argv),
1246 .unsol_matches = unsol_matches,
1247 .unsol_matches_size = ARRAY_SIZE(unsol_matches),
1248 .process_timeout = K_MSEC(2),
1249 };
1250
1251 modem_chat_init(&data->chat, &chat_config);
1252 }
1253
1254 #ifndef CONFIG_PM_DEVICE
1255 modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
1256 #else
1257 pm_device_init_suspended(dev);
1258 #endif /* CONFIG_PM_DEVICE */
1259
1260 return 0;
1261 }
1262
1263 /*
1264 * Every modem uses two custom scripts to initialize the modem and dial out.
1265 *
1266 * The first script is named <dt driver compatible>_init_chat_script, with its
1267 * script commands named <dt driver compatible>_init_chat_script_cmds. This
1268 * script is sent to the modem after it has started up, and must configure the
1269 * modem to use CMUX.
1270 *
1271 * The second script is named <dt driver compatible>_dial_chat_script, with its
1272 * script commands named <dt driver compatible>_dial_chat_script_cmds. This
1273 * script is sent on a DLCI channel in command mode, and must request the modem
1274 * dial out and put the DLCI channel into data mode.
1275 */
1276
1277 #if DT_HAS_COMPAT_STATUS_OKAY(quectel_bg95)
1278 MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_init_chat_script_cmds,
1279 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1280 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1281 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1282 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1283 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1284 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1285 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1286 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1287 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1288 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1289 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1290 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1291 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2",
1292 0));
1293
1294 MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_init_chat_script, quectel_bg95_init_chat_script_cmds,
1295 abort_matches, modem_cellular_chat_callback_handler, 10);
1296
1297 MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_dial_chat_script_cmds,
1298 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1299 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1300 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1301 ok_match),
1302 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1303 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
1304
1305 MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_dial_chat_script, quectel_bg95_dial_chat_script_cmds,
1306 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1307 #endif
1308
1309 #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_gsm_ppp)
1310 MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_init_chat_script_cmds,
1311 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1312 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1313 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1314 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1315 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1316 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1317 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1318 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1319 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1320 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1321 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1322 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1323 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1324 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1325 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1326 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1327 /* The 300ms delay after sending the AT+CMUX command is required
1328 * for some modems to ensure they get enough time to enter CMUX
1329 * mode before sending the first CMUX command. If this delay is
1330 * too short, modems have been observed to simply deadlock,
1331 * refusing to respond to any CMUX command.
1332 */
1333 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300));
1334
1335 MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_init_chat_script, zephyr_gsm_ppp_init_chat_script_cmds,
1336 abort_matches, modem_cellular_chat_callback_handler, 10);
1337
1338 MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_dial_chat_script_cmds,
1339 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1340 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1341 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1342 ok_match),
1343 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1344 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
1345
1346 MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_dial_chat_script, zephyr_gsm_ppp_dial_chat_script_cmds,
1347 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1348 #endif
1349
1350 #if DT_HAS_COMPAT_STATUS_OKAY(simcom_sim7080)
1351 MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_init_chat_script_cmds,
1352 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1353 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1354 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1355 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1356 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1357 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1358 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1359 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1360 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1361 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1362 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1363 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1364 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1365 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1366 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1367 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1368 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300));
1369
1370 MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_init_chat_script, simcom_sim7080_init_chat_script_cmds,
1371 abort_matches, modem_cellular_chat_callback_handler, 10);
1372
1373 MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_dial_chat_script_cmds,
1374 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1375 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1376 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1377 ok_match),
1378 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1379 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
1380
1381 MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_dial_chat_script, simcom_sim7080_dial_chat_script_cmds,
1382 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1383 #endif
1384
1385 #if DT_HAS_COMPAT_STATUS_OKAY(u_blox_sara_r4)
1386 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_init_chat_script_cmds,
1387 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1388 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1389 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1390 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1391 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1392 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1393 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1394 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1395 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1396 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1397 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1398 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1399 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1400 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1401 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1402 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1403 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2",
1404 0));
1405
1406 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_init_chat_script, u_blox_sara_r4_init_chat_script_cmds,
1407 abort_matches, modem_cellular_chat_callback_handler, 10);
1408
1409 MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_dial_chat_script_cmds,
1410 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
1411 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1412 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1413 ok_match),
1414 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1415 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),);
1416
1417 MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r4_dial_chat_script, u_blox_sara_r4_dial_chat_script_cmds,
1418 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1419 #endif
1420
1421 #if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800)
1422 MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_init_chat_script_cmds,
1423 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1424 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1425 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1426 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
1427 MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1428 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1429 MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0", allow_match),
1430 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1431 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1432 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1433 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1434 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1435 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1436 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1437 MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1438 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1439 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2",
1440 0));
1441
1442 MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_init_chat_script, swir_hl7800_init_chat_script_cmds,
1443 abort_matches, modem_cellular_chat_callback_handler, 10);
1444
1445 MODEM_CHAT_SCRIPT_CMDS_DEFINE(swir_hl7800_dial_chat_script_cmds,
1446 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
1447 "\""CONFIG_MODEM_CELLULAR_APN"\"",
1448 ok_match),
1449 MODEM_CHAT_SCRIPT_CMD_RESP("AT+KCNXCFG=1,\"GPRS\",\""
1450 CONFIG_MODEM_CELLULAR_APN
1451 "\",,,\"IPV4\"",
1452 ok_match),
1453 MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
1454 MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0));
1455
1456 MODEM_CHAT_SCRIPT_DEFINE(swir_hl7800_dial_chat_script, swir_hl7800_dial_chat_script_cmds,
1457 dial_abort_matches, modem_cellular_chat_callback_handler, 10);
1458 #endif
1459
1460 #define MODEM_CELLULAR_INST_NAME(name, inst) \
1461 _CONCAT(_CONCAT(_CONCAT(name, _), DT_DRV_COMPAT), inst)
1462
1463 #define MODEM_CELLULAR_DEVICE(inst) \
1464 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
1465 \
1466 static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
1467 .chat_delimiter = {'\r'}, \
1468 .chat_filter = {'\n'}, \
1469 .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
1470 }; \
1471 \
1472 static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \
1473 .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \
1474 .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \
1475 .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \
1476 .power_pulse_duration_ms = 1500, \
1477 .reset_pulse_duration_ms = 100, \
1478 .startup_time_ms = 10000, \
1479 .shutdown_time_ms = 5000, \
1480 .init_chat_script = &_CONCAT(DT_DRV_COMPAT, _init_chat_script), \
1481 .dial_chat_script = &_CONCAT(DT_DRV_COMPAT, _dial_chat_script), \
1482 }; \
1483 \
1484 PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \
1485 \
1486 DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \
1487 &MODEM_CELLULAR_INST_NAME(data, inst), \
1488 &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, NULL);
1489
1490 #define DT_DRV_COMPAT quectel_bg95
1491 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE)
1492 #undef DT_DRV_COMPAT
1493
1494 #define DT_DRV_COMPAT zephyr_gsm_ppp
1495 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE)
1496 #undef DT_DRV_COMPAT
1497
1498 #define DT_DRV_COMPAT simcom_sim7080
1499 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE)
1500 #undef DT_DRV_COMPAT
1501
1502 #define DT_DRV_COMPAT u_blox_sara_r4
1503 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE)
1504 #undef DT_DRV_COMPAT
1505
1506 #define DT_DRV_COMPAT swir_hl7800
1507 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE)
1508 #undef DT_DRV_COMPAT
1509