void __ubmodem_substate_start_disconnect_network(struct ubmodem_s *modem) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int err; MODEM_DEBUGASSERT(modem, modem->level == UBMODEM_LEVEL_NETWORK || modem->level == UBMODEM_LEVEL_GPRS); /* * Disconnect network sequence is: * * 1. Send "AT+COPS=2". * 2. Send "AT+CFUN=0". * */ __ubmodem_network_cleanup(modem); /* Reset sub-state data and initiate sub-state machine work. */ memset(sub, 0, sizeof(*sub)); sub->network_state = NETWORK_SETUP_DISCONNECTING; /* Disable network. */ err = __ubmodem_send_cmd(modem, &cmd_ATpCOPS, set_ATpCOPS_off_handler, sub, "%s", "=2"); MODEM_DEBUGASSERT(modem, err == OK); }
static int network_start_register_handler(struct ubmodem_s *modem, const int timer_id, void * const arg) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int err; MODEM_DEBUGASSERT(modem, modem->creg_timer_id == timer_id); 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); } /* 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 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; }
static void set_ATpCFUN_off_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) { /* * Response handler for AT+CFUN=0 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCFUN); if (resp_status_is_error_or_timeout(info->status)) { __ubmodem_common_failed_command(modem, cmd, info, "=0"); return; } else if (info->status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } /* Done unregistering from network. */ __ubmodem_reached_level(modem, UBMODEM_LEVEL_SIM_ENABLED); }
static void urc_voice_cring_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) { const char *type; uint16_t typelen; /* * URC handler for 'data available for sockets on modem' */ MODEM_DEBUGASSERT(modem, cmd == &urc_ATpCRING); MODEM_DEBUGASSERT(modem, info->status == RESP_STATUS_URC); /* Get type. */ if (!__ubmodem_stream_get_string(&resp_stream, &stream_len, &type, &typelen)) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } /* Just report for now. */ dbg("+CRING: type='%s'\n", type); }
void __ubmodem_substate_start_setup_network(struct ubmodem_s *modem) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int err; MODEM_DEBUGASSERT(modem, modem->level == UBMODEM_LEVEL_SIM_ENABLED); /* * Setup network sequence is: * * 1. Enable "+CREG" URC. * 2. Send "AT+CFUN=1". * 3. Send "AT+COPS=0". * 4. Wait until connected (Wait information from +CREG) * */ MODEM_DEBUGASSERT(modem, modem->creg_urc_registered == false); MODEM_DEBUGASSERT(modem, modem->creg_timer_id == -1); /* Reset sub-state data and initiate sub-state machine work. */ memset(sub, 0, sizeof(*sub)); sub->network_state = NETWORK_SETUP_ENABLING_CREG; /* Setup sub-state clean-up function. */ modem->substate_cleanup_fn = setup_network_cleanup; /* Enable +CREG. */ err = __ubmodem_send_cmd(modem, &cmd_ATpCREG, ATpCREG_handler, sub, "%s", "=1"); MODEM_DEBUGASSERT(modem, err == OK); }
void __ubmodem_recvfrom_socket(struct modem_socket_s *sock) { struct ubmodem_s *modem = sock->modem; int err; size_t inlen; size_t max_stream_len; size_t recvlen; if (sock->is_closed) { /* Socket closed! */ (void)__ubmodem_usrsock_send_response(modem, &sock->req, false, -EPIPE); __ubsocket_work_done(sock); return; } inlen = sock->recv.avail; if (inlen > sock->recv.max_buflen) inlen = sock->recv.max_buflen; if (sock->type == SOCK_DGRAM) { max_stream_len = __ubmodem_stream_max_readbuf_len(&cmd_ATpUSORF); max_stream_len -= INET_ADDRSTRLEN; } else { max_stream_len = __ubmodem_stream_max_readbuf_len(&cmd_ATpUSORD); } MODEM_DEBUGASSERT(modem, inlen > 0); /* sockets state machine should not allow * recv if input buffer has no space * left. */ recvlen = max_stream_len; if (recvlen > MODEM_MAX_BINARY_SOCKET_READ_BYTES) recvlen = MODEM_MAX_BINARY_SOCKET_READ_BYTES; if (recvlen > inlen) recvlen = inlen; if (sock->type == SOCK_DGRAM) { /* Read data and peer address from modem. */ err = __ubmodem_send_cmd(modem, &cmd_ATpUSORF, socket_recvfrom_handler, sock, "=%d,%d", sock->modem_sd, recvlen); MODEM_DEBUGASSERT(modem, err == OK); } else { /* Read data from modem. */ err = __ubmodem_send_cmd(modem, &cmd_ATpUSORD, socket_recvfrom_handler, sock, "=%d,%d", sock->modem_sd, recvlen); MODEM_DEBUGASSERT(modem, err == OK); } }
static int network_register_timeout_handler(struct ubmodem_s *modem, const int timer_id, void * const arg) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; struct timespec curr_ts; const char *reason; int ret; MODEM_DEBUGASSERT(modem, modem->creg_timer_id == timer_id); 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); } (void)clock_gettime(CLOCK_MONOTONIC, &curr_ts); if (curr_ts.tv_sec - sub->net_reg_start_ts.tv_sec <= MODEM_CMD_NETWORK_REGISTRATION_TIMEOUT / 10) { /* Too soon, reregister timer. */ ret = __ubmodem_set_timer(modem, NETWORK_REGISTRATION_CHECK_SECS * 1000, &network_register_timeout_handler, sub); MODEM_DEBUGASSERT(modem, ret != ERROR); modem->creg_timer_id = ret; ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, true); return OK; } /* Could not register in time. Disable RF. */ if (timer_id == -1) reason = "NETWORK: Denied."; else reason = "NETWORK: Timeout."; /* Mark for retry, 'level transition failed' can modify the actual target * level. */ __ubmodem_network_cleanup(modem); __ubmodem_retry_current_level(modem, UBMODEM_LEVEL_SIM_ENABLED); /* Failed to connect network. */ __ubmodem_level_transition_failed(modem, "%s", reason); return OK; }
static void set_ATpCOPS_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) { struct modem_sub_setup_network_s *sub = priv; int ret; int status = info->status; /* * Response handler for AT+COPS=0 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCOPS); if (status == RESP_STATUS_CME_ERROR) { if (handle_cops_cme_error(modem, info)) return; } else if (resp_status_is_error_or_timeout(status)) { __ubmodem_common_failed_command(modem, cmd, info, "=0"); return; } else if (status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } /* * Now waiting for +CREG URC. * * Register timer for timeout. */ sub->network_state = NETWORK_SETUP_WAITING_NETWORK_REGISTRATION; ret = __ubmodem_set_timer(modem, MODEM_CMD_NETWORK_TIMEOUT * 100, &network_register_timer_handler, sub); if (ret == ERROR) { /* Error here? Add assert? Or just try bailout? */ MODEM_DEBUGASSERT(modem, false); (void)network_register_timer_handler(modem, -1, sub); return; } modem->creg_timer_id = ret; }
static void retry_ATpCOPS_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) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int status = info->status; int ret; /* * Response handler for retried AT+COPS=0 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCOPS); if (status == RESP_STATUS_CME_ERROR) { if (handle_cops_cme_error(modem, info)) return; } else if (resp_status_is_error_or_timeout(status)) { __ubmodem_common_failed_command(modem, cmd, info, "=0"); return; } else if (info->status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } DEBUGASSERT( sub->network_state == NETWORK_SETUP_RETRYING_NETWORK_REGISTRATION); sub->network_state = NETWORK_SETUP_WAITING_NETWORK_REGISTRATION; /* * Now waiting for +CREG URC. * * Register timer for timeout. */ ret = __ubmodem_set_timer(modem, NETWORK_REGISTRATION_CHECK_SECS * 1000, &network_register_timeout_handler, sub); MODEM_DEBUGASSERT(modem, ret != ERROR); modem->creg_timer_id = ret; ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, true); }
static void ATA_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) { uintptr_t mutepriv = (uintptr_t)priv; bool mute_mic = mutepriv >> 1; bool mute_speaker = mutepriv & 1; if (resp_status_is_error_or_timeout(info->status)) { int err; /* In case of error, check CMEE setting to detect stuck hardware. */ err = __ubmodem_check_cmee_status(modem, modem_audio_check_cmee, modem); MODEM_DEBUGASSERT(modem, err == OK); return; } else if (info->status == RESP_STATUS_OK) { /* Configure audio. */ ubmodem_audio_setup(modem, !mute_speaker, !mute_mic); } /* Reactions to call state changes are based on +UCALLSTAT. Just complete * task work. */ /* Update main state machine. */ __ubmodem_change_state(modem, MODEM_STATE_WAITING); }
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 void retry_ATpCOPS_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) { struct modem_sub_setup_network_s *sub = priv; int status = info->status; /* * Response handler for retried AT+COPS=0 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCOPS); if (status == RESP_STATUS_CME_ERROR) { if (handle_cops_cme_error(modem, info)) return; } else if (resp_status_is_error_or_timeout(status)) { __ubmodem_common_failed_command(modem, cmd, info, "=0"); return; } else if (info->status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } DEBUGASSERT( sub->network_state == NETWORK_SETUP_RETRYING_NETWORK_REGISTRATION); sub->network_state = NETWORK_SETUP_WAITING_NETWORK_REGISTRATION; if (sub->received_creg_while_retrying > 0) { ubdbg("Handling deferred +CREG: %d\n", sub->received_creg_while_retrying); /* Report successful cellular network connection. */ sub->keep_creg_urc = true; __ubmodem_reached_level(modem, UBMODEM_LEVEL_NETWORK); } }
static void config_audio_out_ctrl_gpio(struct ubmodem_s *modem, int pin, bool set) { int err; err = __ubmodem_send_cmd(modem, &cmd_ATpUGPIOC, __ubmodem_cmdprompt_generic_config_handler, (void *)&cmd_ATpUGPIOC, "=%d,0,%d", pin, set); MODEM_DEBUGASSERT(modem, err == OK); }
int __ubmodem_usrsock_handle_recvfrom_request(struct ubmodem_s *modem, void *reqbuf) { struct usrsock_request_recvfrom_s *req = reqbuf; struct modem_socket_s *sock; int err; /* Get sockets for request. */ sock = __ubmodem_socket_get_by_usockid(modem, req->usockid); if (!sock) { /* Give error result. */ err = -EBADF; goto err_out; } MODEM_DEBUGASSERT(modem, sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM); /* Check if sockets is closed. */ if (sock->is_closed || sock->modem_sd < 0) { err = -EPIPE; goto err_out; } if (sock->recv.avail == 0) { /* No data available at modem. */ err = -EAGAIN; goto err_out; } /* TODO: Check for pending blocking operation (TCP connect) */ /* Prepare to receive data from modem. */ sock->req = req->head; sock->is_waiting_recv = true; sock->recv.max_addrlen = req->max_addrlen; sock->recv.max_buflen = req->max_buflen; __ubsocket_update_state(sock); __ubmodem_wake_waiting_state(modem, false); /* Report that request has been read and processing has started. */ return __ubmodem_usrsock_send_response(modem, reqbuf, true, -EINPROGRESS); err_out: return __ubmodem_usrsock_send_response(modem, reqbuf, false, err); }
static void set_ATpCOPS_off_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) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int ret; /* * Response handler for AT+COPS=2 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCOPS); if (resp_status_is_error_or_timeout(info->status)) { __ubmodem_common_failed_command(modem, cmd, info, "=2"); return; } else if (info->status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } /* Wait for sometime so modem can complete unregistering from network. */ ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, true); ret = __ubmodem_set_timer(modem, 1500, &network_unregister_timer_handler, sub); if (ret == ERROR) { /* Error here? Add assert? Or just try bailout? */ MODEM_DEBUGASSERT(modem, false); (void)network_unregister_timer_handler(modem, -1, sub); return; } }
static void config_enable_urc_common(struct ubmodem_s *modem, const struct at_cmd_def_s *cmd) { int err; __ubmodem_voice_control_setup(modem); err = __ubmodem_send_cmd(modem, cmd, __ubmodem_cmdprompt_generic_config_handler, (void *)cmd, "=1"); MODEM_DEBUGASSERT(modem, err == OK); }
static void ATpCREG_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) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int err; /* * Response handler for AT+CREG=1 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCREG); if (resp_status_is_error_or_timeout(info->status)) { __ubmodem_common_failed_command(modem, cmd, info, "=1"); return; } if (info->status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } /* Register "+CREG" URC handler. */ __ubparser_register_response_handler(&modem->parser, &urc_ATpCREG, registration_urc_pCREG_handler, sub, true); modem->creg_urc_registered = true; sub->network_state = NETWORK_SETUP_ENABLING_RF; /* Enable modem RF. */ err = __ubmodem_send_cmd(modem, &cmd_ATpCFUN, ATpCFUN_handler, sub, "%s", "=1"); MODEM_DEBUGASSERT(modem, err == OK); }
static void ATpCFUN_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) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int err; /* * Response handler for AT+CFUN=1 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCFUN); if (resp_status_is_error_or_timeout(info->status)) { __ubmodem_common_failed_command(modem, cmd, info, "=1"); return; } if (info->status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } /* * Modem RF enabled, now disable previous automatic network registration. * +CREG:0 will be received and +COPS=0 will be issued to start new automatic * network registration. */ sub->network_state = NETWORK_SETUP_STARTING_NETWORK_REGISTRATION; (void)clock_gettime(CLOCK_MONOTONIC, &sub->net_reg_start_ts); err = __ubmodem_send_cmd(modem, &cmd_ATpCOPS, disable_ATpCOPS_handler, sub, "%s", "=2"); MODEM_DEBUGASSERT(modem, err == OK); }
static void ATpCFUN_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) { struct modem_sub_setup_network_s *sub = priv; int err; /* * Response handler for AT+CFUN=1 */ MODEM_DEBUGASSERT(modem, cmd == &cmd_ATpCFUN); if (resp_status_is_error_or_timeout(info->status)) { __ubmodem_common_failed_command(modem, cmd, info, "=1"); return; } if (info->status != RESP_STATUS_OK) { MODEM_DEBUGASSERT(modem, false); /* Should not get here. */ return; } /* * Modem RF enabled, now start automatic network registration. */ sub->network_state = NETWORK_SETUP_STARTING_NETWORK_REGISTRATION; err = __ubmodem_send_cmd(modem, &cmd_ATpCOPS, set_ATpCOPS_handler, sub, "%s", "=0"); MODEM_DEBUGASSERT(modem, err == OK); }
static int network_retry_registration_timer_handler(struct ubmodem_s *modem, const int timer_id, void * const arg) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int err; MODEM_DEBUGASSERT(modem, modem->creg_timer_id == timer_id); 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); } DEBUGASSERT( sub->network_state == NETWORK_SETUP_RETRYING_NETWORK_REGISTRATION); if (sub->received_creg_while_retrying > 0) { ubdbg("Handling deferred +CREG: %d\n", sub->received_creg_while_retrying); network_registration_successed(modem, sub); } else { err = __ubmodem_send_cmd(modem, &cmd_ATpCOPS, retry_ATpCOPS_handler, sub, "%s", "=0"); MODEM_DEBUGASSERT(modem, err == OK); } return OK; }
static int network_unregister_timer_handler(struct ubmodem_s *modem, const int timer_id, void * const arg) { struct modem_sub_setup_network_s *sub = arg; int err; /* Send +CFUN=0 */ err = __ubmodem_send_cmd(modem, &cmd_ATpCFUN, set_ATpCFUN_off_handler, sub, "%s", "=0"); MODEM_DEBUGASSERT(modem, err == OK); return OK; }
static int network_unregister_timer_handler(struct ubmodem_s *modem, const int timer_id, void * const arg) { struct modem_sub_setup_network_s *sub = &modem->sub.setup_network; int err; /* Send +CFUN=0 */ ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_HIGH, false); err = __ubmodem_send_cmd(modem, &cmd_ATpCFUN, set_ATpCFUN_off_handler, sub, "%s", "=0"); MODEM_DEBUGASSERT(modem, err == OK); return OK; }
static int start_task_voice_answer(struct ubmodem_s *modem, void *priv) { int err; if (modem->level < UBMODEM_LEVEL_NETWORK) { return ERROR; } /* Send answer call command 'ATA' */ err = __ubmodem_send_cmd(modem, &cmd_ATA, ATA_handler, priv, ""); MODEM_DEBUGASSERT(modem, err == OK); return OK; }
static int start_task_voice_hangup(struct ubmodem_s *modem, void *priv) { int err; if (modem->level < UBMODEM_LEVEL_NETWORK) { return ERROR; } /* Send hangup call command 'AT+CHUP' */ err = __ubmodem_send_cmd(modem, &cmd_ATpCHUP, ATpCHUP_handler, modem, ""); MODEM_DEBUGASSERT(modem, err == OK); return OK; }
static void voice_probe_check_cmee_result(struct ubmodem_s *modem, bool cmee_ok, int cmee_setting, void *priv) { int err; /* Release main state machine for next task. */ __ubmodem_change_state(modem, MODEM_STATE_WAITING); if (!cmee_ok && modem->voice.probe_fails++ >= VOICE_MODEM_PROBE_FAILS) { /* Modem HW is in unknown state, attempt to recover. */ err = __ubmodem_recover_stuck_hardware(modem); MODEM_DEBUGASSERT(modem, err != ERROR); } }
static void modem_voice_pm_activity(struct ubmodem_s *modem, bool ringing_or_active) { if (ringing_or_active == modem->voice.pm_activity_enabled) { /* Already in this state. */ return; } modem->voice.pm_activity_enabled = ringing_or_active; modem->voice.probe_fails = 0; if (modem->voice.probe_timerid >= 0) { __ubmodem_remove_timer(modem, modem->voice.probe_timerid); modem->voice.probe_timerid = -1; } if (ringing_or_active) { /* Voice call incoming, ringing. After ringing call is eventually * disconnected. Report low activity so that we get disconnect URC from * modem after hangup (no ring-indication anymore to wake-up MCU). */ ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_LOW, true); /* Start probing to detect modem hang-ups (low voltage situation etc). */ 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); } else { /* Voice call disconnected, report change of activity to * power-management. */ ubmodem_pm_set_activity(modem, UBMODEM_PM_ACTIVITY_LOW, false); } }
static void modem_audio_check_cmee(struct ubmodem_s *modem, bool cmee_ok, int cmee_setting, void *priv) { if (!cmee_ok) { int err; /* Modem hardware stuck or reseted, launch task to restore function. */ err = __ubmodem_recover_stuck_hardware(modem); MODEM_DEBUGASSERT(modem, err != ERROR); } /* Reactions to call state changes are based on +UCALLSTAT. Just complete * task work. */ /* Update main state machine. */ __ubmodem_change_state(modem, MODEM_STATE_WAITING); }
static int voice_probe_check_cmee(struct ubmodem_s *modem, void *priv) { int err; modem->voice.probe_task_queued = false; if (!modem->voice.pm_activity_enabled) { return ERROR; } if (modem->level < UBMODEM_LEVEL_CMD_PROMPT) { return ERROR; } /* Check CMEE setting to see if modem has reseted or not. */ err = __ubmodem_check_cmee_status(modem, voice_probe_check_cmee_result, modem); MODEM_DEBUGASSERT(modem, err == OK); return OK; }
static void ATpCHUP_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) { if (resp_status_is_error_or_timeout(info->status)) { int err; /* In case of error, check CMEE setting to detect stuck hardware. */ err = __ubmodem_check_cmee_status(modem, modem_audio_check_cmee, modem); MODEM_DEBUGASSERT(modem, err == OK); return; } /* Reactions to call state changes are based on +UCALLSTAT. Just complete * task work. */ /* Update main state machine. */ __ubmodem_change_state(modem, MODEM_STATE_WAITING); }