예제 #1
0
/**
 * @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;
    }
}
예제 #2
0
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);
}