static int network_reregister_timer_handler(struct ubmodem_s *modem, const int timer_id, void * const arg) { MODEM_DEBUGASSERT(modem, modem->creg_timer_id == timer_id); /* One-shot timer, not registered anymore. */ if (timer_id != -1) { /* One-shot timer, not registered anymore. */ modem->creg_timer_id = -1; ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, 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, reregister_network_failed, NULL); return OK; }
static int voice_probe_fn(struct ubmodem_s *modem, const int timer_id, void * const arg) { int ret; modem->voice.probe_timerid = -1; if (!modem->voice.pm_activity_enabled) { return OK; } /* Start CMEE probe task. */ if (!modem->voice.probe_task_queued) { ret = __ubmodem_add_task(modem, voice_probe_check_cmee, modem); MODEM_DEBUGASSERT(modem, ret != ERROR); modem->voice.probe_task_queued = true; } /* Reregister timer. */ modem->voice.probe_timerid = __ubmodem_set_timer(modem, VOICE_MODEM_PROBE_SECS * 1000, voice_probe_fn, modem); MODEM_DEBUGASSERT(modem, modem->voice.probe_timerid >= 0); return OK; }
void ubmodem_voice_hangup(struct ubmodem_s *modem) { DEBUGASSERT(modem); if (modem->level < UBMODEM_LEVEL_NETWORK) { return; } (void)__ubmodem_add_task(modem, start_task_voice_hangup, NULL); }
void ubmodem_voice_answer(struct ubmodem_s *modem, bool mute_mic, bool mute_speaker) { uintptr_t mutepriv; DEBUGASSERT(modem); if (modem->level < UBMODEM_LEVEL_NETWORK) { return; } mutepriv = (mute_mic << 1) | mute_speaker; (void)__ubmodem_add_task(modem, start_task_voice_answer, (void *)mutepriv); }
static int network_reregister_timer_handler(struct ubmodem_s *modem, const int timer_id, void * const arg) { /* One-shot timer, not registered anymore. */ if (timer_id != -1) { /* One-shot timer, not registered anymore. */ modem->creg_timer_id = -1; } /* 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, reregister_network_failed, NULL); return OK; }
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; } } }