void __ubmodem_voice_control_cleanup(struct ubmodem_s *modem) { if (!modem->voice_urcs_registered) return; modem_voice_disconnected(modem, false); ubmodem_audio_cleanup(modem); __ubparser_unregister_response_handler(&modem->parser, urc_ATpCRING.name); __ubparser_unregister_response_handler(&modem->parser, urc_ATpUCALLSTAT.name); __ubparser_unregister_response_handler(&modem->parser, urc_ATpCLIP.name); modem->voice_urcs_registered = false; memset(&modem->voice, 0, sizeof(modem->voice)); }
void __ubmodem_network_cleanup(struct ubmodem_s *modem) { if (modem->level == UBMODEM_LEVEL_GPRS) { /* Uninitialize GRPS */ __ubmodem_gprs_cleanup(modem); } if (modem->level >= UBMODEM_LEVEL_NETWORK) { if (modem->creg_timer_id != -1) { /* Unregister timeout. */ __ubmodem_remove_timer(modem, modem->creg_timer_id); modem->creg_timer_id = -1; ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, false); } if (modem->creg_urc_registered) { /* Unregister +CREG URC */ __ubparser_unregister_response_handler(&modem->parser, urc_ATpCREG.name); modem->creg_urc_registered = false; } } }
static void network_registration_successed(struct ubmodem_s *modem, struct modem_sub_setup_network_s *sub) { /* Switch +CREG URC handler to monitor variant. */ __ubparser_unregister_response_handler(&modem->parser, urc_ATpCREG.name); __ubparser_register_response_handler(&modem->parser, &urc_ATpCREG, monitor_urc_pCREG_handler, modem, true); DEBUGASSERT(modem->creg_urc_registered); /* Report successful cellular network connection. */ sub->keep_creg_urc = true; __ubmodem_reached_level(modem, UBMODEM_LEVEL_NETWORK); }
static void setup_network_cleanup(struct ubmodem_s *modem) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; if (modem->creg_timer_id != -1) { /* Unregister timeout. */ __ubmodem_remove_timer(modem, modem->creg_timer_id); modem->creg_timer_id = -1; } if (modem->creg_urc_registered && !sub->keep_creg_urc) { /* Unregister +CREG URC */ __ubparser_unregister_response_handler(&modem->parser, urc_ATpCREG.name); modem->creg_urc_registered = false; } }
static void monitor_urc_pCREG_handler(struct ubmodem_s *modem, const struct at_cmd_def_s *cmd, const struct at_resp_info_s *info, const uint8_t *resp_stream, size_t stream_len, void *priv) { int8_t val; int ret; (void)ret; /* * Response handler for +CREG URC. */ MODEM_DEBUGASSERT(modem, cmd == &urc_ATpCREG); if (info->status != RESP_STATUS_URC) { /* Should not happen. */ MODEM_DEBUGASSERT(modem, false); return; } if (!__ubmodem_stream_get_int8(&resp_stream, &stream_len, &val)) { /* Should not happen. */ MODEM_DEBUGASSERT(modem, false); return; } dbg("Network registration URC, +CREG=%d.\n", val); if (val >= 0 && val < ARRAY_SIZE(creg_strings)) { dbg("%s\n", creg_strings[val]); } else { dbg("Unknown +CREG status: %d\n", val); } if (modem->creg_timer_id >= 0) { __ubmodem_remove_timer(modem, modem->creg_timer_id); modem->creg_timer_id = -1; ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, false); } switch (val) { default: /* Unknown? */ case 1: /* Switched to home network? */ case 5: /* Switched to roaming? */ return; case 2: /* Looking for connection. */ #ifdef CONFIG_UBMODEM_CREG_WAIT_NETWORK_TO_RESTORE /* Start connection search timeout timer. */ ret = __ubmodem_set_timer(modem, MODEM_CMD_NETWORK_TIMEOUT * 100, &network_reregister_timer_handler, modem); MODEM_DEBUGASSERT(modem, ret != ERROR); modem->creg_timer_id = ret; ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, true); return; #else /* Reset network through SIM reinitialization. Appears to work * better in roaming conditions. TODO: Study why, do we understand * function of modem in low-signal environments properly? */ #endif case 3: /* Registration failed? */ case 4: /* Unknown registration error? */ case 0: /* MT not searching for connection. */ /* Unregister +CREG URC */ __ubparser_unregister_response_handler(&modem->parser, urc_ATpCREG.name); modem->creg_urc_registered = false; /* Issue new task. We cannot issue new state machine work from * URC 'context' as other work might be active in main state * machine. Task will be run with main state machine in proper * state. */ __ubmodem_add_task(modem, retry_network_through_sim, NULL); return; } }
static void urc_pCREG_handler(struct ubmodem_s *modem, const struct at_cmd_def_s *cmd, const struct at_resp_info_s *info, const uint8_t *resp_stream, size_t stream_len, void *priv) { int8_t val; int err; int ret; /* * Response handler for +CREG URC. */ MODEM_DEBUGASSERT(modem, cmd == &urc_ATpCREG); if (info->status != RESP_STATUS_URC) { /* Should not happen. */ MODEM_DEBUGASSERT(modem, false); return; } if (!__ubmodem_stream_get_int8(&resp_stream, &stream_len, &val)) { /* Should not happen. */ MODEM_DEBUGASSERT(modem, false); return; } dbg("Network registration URC, +CREG=%d.\n", val); if (val >= 0 && val < ARRAY_SIZE(creg_strings)) { dbg("%s\n", creg_strings[val]); } else { dbg("Unknown +CREG status: %d\n", val); } if (modem->level < UBMODEM_LEVEL_NETWORK) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; DEBUGASSERT(modem->state == MODEM_STATE_IN_SUBSTATE); if (sub->network_state < NETWORK_SETUP_WAITING_NETWORK_REGISTRATION) { /* Not ready yet, spurious +CREG URC? */ ubdbg("Ignored spurious +CREG URC.\n"); return; } switch (val) { case 1: case 5: /* * If 'val' is 1, registered: home network. * If 'val' is 5, registered: roamed. */ if (sub->network_state == NETWORK_SETUP_RETRYING_NETWORK_REGISTRATION) { /* Cannot do state transition to UBMODEM_LEVEL_NETWORK right now * as still retrying AT+COPS=0. Defer handling to * retry_ATpCOPS_handler. */ sub->received_creg_while_retrying = val; } else { /* Report successful cellular network connection. */ sub->keep_creg_urc = true; __ubmodem_reached_level(modem, UBMODEM_LEVEL_NETWORK); } return; case 0: /* * MT not searching for connection. */ if (sub->network_state == NETWORK_SETUP_WAITING_NETWORK_REGISTRATION) { /* Keep retrying automatic network registration until timeout. */ sub->network_state = NETWORK_SETUP_RETRYING_NETWORK_REGISTRATION; sub->received_creg_while_retrying = -1; err = __ubmodem_send_cmd(modem, &cmd_ATpCOPS, retry_ATpCOPS_handler, sub, "%s", "=0"); MODEM_DEBUGASSERT(modem, err == OK); } return; case 4: /* * If 'val' is 4, unknown registration error. */ /* no break */ case 3: /* * If 'val' is 3, registration was denied. */ /* Perform fail-over code from timeout handler. */ network_register_timer_handler(modem, -1, sub); return; case 2: /* * If 'val' is 2, modem is trying to register. */ return; default: /* * Unknown. */ return; } } else { /* Current level is UBMODEM_LEVEL_NETWORK or higher. */ switch (val) { default: /* Unknown? */ case 1: /* Switched to home network? */ case 5: /* Switched to roaming? */ if (modem->creg_timer_id >= 0) { __ubmodem_remove_timer(modem, modem->creg_timer_id); modem->creg_timer_id = -1; } return; case 2: /* Looking for connection. */ /* Start connection search timeout timer. */ ret = __ubmodem_set_timer(modem, MODEM_CMD_NETWORK_TIMEOUT * 100, &network_reregister_timer_handler, modem); if (ret == ERROR) { /* Error here? Add assert? Or just try bailout? */ MODEM_DEBUGASSERT(modem, false); (void)network_reregister_timer_handler(modem, -1, modem); return; } modem->creg_timer_id = ret; return; case 3: /* Registration failed? */ case 4: /* Unknown registration error? */ case 0: /* MT not searching for connection. */ /* Unregister +CREG URC */ __ubparser_unregister_response_handler(&modem->parser, urc_ATpCREG.name); modem->creg_urc_registered = false; /* Issue new task. We cannot issue new state machine work from * URC 'context' as other work might be active in main state * machine. Task will be run with main state machine in proper * state. */ __ubmodem_add_task(modem, retry_network_through_sim, NULL); return; } } }