/** * @brief PPP status callback which is called on PPP status change (up, down, …) by lwIP core thread * * @param pcb PPP control block * @param err_code Error code * @param ctx Context of callback */ static void on_ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx) { struct netif *pppif = ppp_netif(pcb); modem_dte_t *dte = (modem_dte_t *)(ctx); esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent); ppp_client_ip_info_t ipinfo = {0}; switch (err_code) { case PPPERR_NONE: /* Connected */ ipinfo.ip = pppif->ip_addr.u_addr.ip4; ipinfo.gw = pppif->gw.u_addr.ip4; ipinfo.netmask = pppif->netmask.u_addr.ip4; ipinfo.ns1 = dns_getserver(0).u_addr.ip4; ipinfo.ns2 = dns_getserver(1).u_addr.ip4; esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, MODEM_EVENT_PPP_CONNECT, &ipinfo, sizeof(ipinfo), 0); break; case PPPERR_PARAM: ESP_LOGE(MODEM_TAG, "Invalid parameter"); break; case PPPERR_OPEN: ESP_LOGE(MODEM_TAG, "Unable to open PPP session"); break; case PPPERR_DEVICE: ESP_LOGE(MODEM_TAG, "Invalid I/O device for PPP"); break; case PPPERR_ALLOC: ESP_LOGE(MODEM_TAG, "Unable to allocate resources"); break; case PPPERR_USER: /* User interrupt */ esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, MODEM_EVENT_PPP_STOP, NULL, 0, 0); /* Free the PPP control block */ pppapi_free(esp_dte->ppp); break; case PPPERR_CONNECT: /* Connection lost */ esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, MODEM_EVENT_PPP_DISCONNECT, NULL, 0, 0); break; case PPPERR_AUTHFAIL: ESP_LOGE(MODEM_TAG, "Failed authentication challenge"); break; case PPPERR_PROTOCOL: ESP_LOGE(MODEM_TAG, "Failed to meet protocol"); break; case PPPERR_PEERDEAD: ESP_LOGE(MODEM_TAG, "Connection timeout"); break; case PPPERR_IDLETIMEOUT: ESP_LOGE(MODEM_TAG, "Idle Timeout"); break; case PPPERR_CONNECTTIME: ESP_LOGE(MODEM_TAG, "Max connect time reached"); break; case PPPERR_LOOPBACK: ESP_LOGE(MODEM_TAG, "Loopback detected"); break; default: ESP_LOGE(MODEM_TAG, "Unknown error code %d", err_code); break; } }
STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { ppp_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args > 1) { if (mp_obj_is_true(args[1])) { if (self->active) { return mp_const_true; } self->pcb = pppapi_pppos_create(&self->pppif, ppp_output_callback, ppp_status_cb, self); if (self->pcb == NULL) { mp_raise_msg(&mp_type_RuntimeError, "init failed"); } pppapi_set_default(self->pcb); pppapi_connect(self->pcb, 0); xTaskCreate(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle); self->active = true; } else { if (!self->active) { return mp_const_false; } // Wait for PPPERR_USER, with timeout pppapi_close(self->pcb, 0); uint32_t t0 = mp_hal_ticks_ms(); while (!self->clean_close && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { mp_hal_delay_ms(10); } // Shutdown task xTaskNotifyGive(self->client_task_handle); t0 = mp_hal_ticks_ms(); while (self->client_task_handle != NULL && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { mp_hal_delay_ms(10); } // Release PPP pppapi_free(self->pcb); self->pcb = NULL; self->active = false; self->connected = false; self->clean_close = false; } } return mp_obj_new_bool(self->active); }