/**
 * RIL_REQUEST_VOICE_REGISTRATION_STATE
 *
 * Request current registration state.
 */
void requestRegistrationState(int request, void *data,
                              size_t datalen, RIL_Token t)
{
    (void) data; (void) datalen, (void)request;
    int err = 0;
    const char resp_size = 15;
    int response[resp_size];
    char *responseStr[resp_size];
    ATResponse *cgreg_resp = NULL, *e2reg_resp = NULL;
    char *line;
    int commas = 0;
    int skip, cs_status = 0;
    int i;

    /* IMPORTANT: Will take screen state lock here. Make sure to always call
                  releaseScreenStateLock BEFORE returning! */
    getScreenStateLock();
    if (!getScreenState()) {
        (void)at_send_command("AT+CREG=2"); /* Ignore the response, not VITAL. */
    }

    /* Setting default values in case values are not returned by AT command */
    for (i = 0; i < resp_size; i++)
        responseStr[i] = NULL;

    memset(response, 0, sizeof(response));

    err = at_send_command_singleline("AT+CREG?", "+CREG:", &cgreg_resp);

    if (err != AT_NOERROR)
        goto error;

    line = cgreg_resp->p_intermediates->line;

    err = at_tok_start(&line);
    if (err < 0)
        goto error;

    /*
     * The solicited version of the CREG response is
     * +CREG: n, stat, [lac, cid]
     * and the unsolicited version is
     * +CREG: stat, [lac, cid]
     * The <n> parameter is basically "is unsolicited creg on?"
     * which it should always be.
     *
     * Now we should normally get the solicited version here,
     * but the unsolicited version could have snuck in
     * so we have to handle both.
     *
     * Also since the LAC and CID are only reported when registered,
     * we can have 1, 2, 3, or 4 arguments here.
     *
     * finally, a +CGREG: answer may have a fifth value that corresponds
     * to the network type, as in;
     *
     *   +CGREG: n, stat [,lac, cid [,networkType]]
     */

    /* Count number of commas */
    err = at_tok_charcounter(line, ',', &commas);

    if (err < 0)
        goto error;

    switch (commas) {
    case 0:                    /* +CREG: <stat> */
        err = at_tok_nextint(&line, &response[0]);
        if (err < 0)
            goto error;

        response[1] = -1;
        response[2] = -1;
        break;

    case 1:                    /* +CREG: <n>, <stat> */
        err = at_tok_nextint(&line, &skip);
        if (err < 0)
            goto error;

        err = at_tok_nextint(&line, &response[0]);
        if (err < 0)
            goto error;

        response[1] = -1;
        response[2] = -1;
        if (err < 0)
            goto error;
        break;
    case 2:                    /* +CREG: <stat>, <lac>, <cid> */
        err = at_tok_nextint(&line, &response[0]);
        if (err < 0)
            goto error;

        err = at_tok_nexthexint(&line, &response[1]);
        if (err < 0)
            goto error;

        err = at_tok_nexthexint(&line, &response[2]);
        if (err < 0)
            goto error;
        break;
    case 3:                    /* +CREG: <n>, <stat>, <lac>, <cid> */
    case 4:                    /* +CREG: <n>, <stat>, <lac>, <cid>, <?> */
        err = at_tok_nextint(&line, &skip);
        if (err < 0)
            goto error;

        err = at_tok_nextint(&line, &response[0]);
        if (err < 0)
            goto error;

        err = at_tok_nexthexint(&line, &response[1]);
        if (err < 0)
            goto error;

        err = at_tok_nexthexint(&line, &response[2]);
        if (err < 0)
            goto error;
        break;
    default:
        goto error;
    }

    s_registrationDeniedReason = DEFAULT_VALUE;

    if (response[0] == CGREG_STAT_REG_DENIED) {
        err = at_send_command_singleline("AT*E2REG?", "*E2REG:", &e2reg_resp);

        if (err != AT_NOERROR)
            goto error;

        line = e2reg_resp->p_intermediates->line;
        err = at_tok_start(&line);
        if (err < 0)
            goto error;

        err = at_tok_nextint(&line, &skip);
        if (err < 0)
            goto error;

        err = at_tok_nextint(&line, &cs_status);
        if (err < 0)
            goto error;

        response[13] = convertRegistrationDeniedReason(cs_status);
        s_registrationDeniedReason = response[13];
        err = asprintf(&responseStr[13], "%08x", response[13]);
        if (err < 0)
            goto error;
    }

    err = asprintf(&responseStr[0], "%d", response[0]);
    if (err < 0)
            goto error;

    if (response[1] > 0)
        err = asprintf(&responseStr[1], "%04x", response[1]);
    if (err < 0)
        goto error;

    if (response[2] > 0)
        err = asprintf(&responseStr[2], "%08x", response[2]);
    if (err < 0)
        goto error;

    if (response[0] == CGREG_STAT_REG_HOME_NET ||
        response[0] == CGREG_STAT_ROAMING)
        responseStr[3] = getNetworkType(0);

    RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr,
                          resp_size * sizeof(char *));

finally:
    if (!getScreenState())
        (void)at_send_command("AT+CREG=0");

    releaseScreenStateLock(); /* Important! */

    for (i = 0; i < resp_size; i++)
        free(responseStr[i]);

    at_response_free(cgreg_resp);
    at_response_free(e2reg_resp);
    return;

error:
    LOGE("%s() Must never return an error when radio is on", __func__);
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
/**
 * RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
 *
 * Scans for available networks.
*/
void requestQueryAvailableNetworks(void *data, size_t datalen, RIL_Token t)
{
    #define QUERY_NW_NUM_PARAMS 4

    /*
     * AT+COPS=?
     *   +COPS: [list of supported (<stat>,long alphanumeric <oper>
     *           ,short alphanumeric <oper>,numeric <oper>[,<AcT>])s]
     *          [,,(list of supported <mode>s),(list of supported <format>s)]
     *
     *   <stat>
     *     0 = unknown
     *     1 = available
     *     2 = current
     *     3 = forbidden
     */
    (void) data; (void) datalen;
    int err = 0;
    ATResponse *atresponse = NULL;
    const char *statusTable[] =
        { "unknown", "available", "current", "forbidden" };
    char **responseArray = NULL;
    char *p;
    int n = 0;
    int i = 0;

    err = at_send_command_multiline("AT+COPS=?", "+COPS:", &atresponse);
    if (err != AT_NOERROR)
        goto error;

    p = atresponse->p_intermediates->line;

    /* count number of '('. */
    err = at_tok_charcounter(p, '(', &n);
    if (err < 0) goto error;

    /* Allocate array of strings, blocks of 4 strings. */
    responseArray = alloca(n * QUERY_NW_NUM_PARAMS * sizeof(char *));

    /* Loop and collect response information into the response array. */
    for (i = 0; i < n; i++) {
        int status = 0;
        char *line = NULL;
        char *s = NULL;
        char *longAlphaNumeric = NULL;
        char *shortAlphaNumeric = NULL;
        char *numeric = NULL;
        char *remaining = NULL;

        s = line = getFirstElementValue(p, "(", ")", &remaining);
        p = remaining;

        if (line == NULL) {
            LOGE("%s() Null pointer while parsing COPS response."
	         "This should not happen.", __func__);
            break;
        }
        /* <stat> */
        err = at_tok_nextint(&line, &status);
        if (err < 0)
            goto error;

        /* long alphanumeric <oper> */
        err = at_tok_nextstr(&line, &longAlphaNumeric);
        if (err < 0)
            goto error;

        /* short alphanumeric <oper> */
        err = at_tok_nextstr(&line, &shortAlphaNumeric);
        if (err < 0)
            goto error;

        /* numeric <oper> */
        err = at_tok_nextstr(&line, &numeric);
        if (err < 0)
            goto error;

        responseArray[i * QUERY_NW_NUM_PARAMS + 0] = alloca(strlen(longAlphaNumeric) + 1);
        strcpy(responseArray[i * QUERY_NW_NUM_PARAMS + 0], longAlphaNumeric);

        responseArray[i * QUERY_NW_NUM_PARAMS + 1] = alloca(strlen(shortAlphaNumeric) + 1);
        strcpy(responseArray[i * QUERY_NW_NUM_PARAMS + 1], shortAlphaNumeric);

        responseArray[i * QUERY_NW_NUM_PARAMS + 2] = alloca(strlen(numeric) + 1);
        strcpy(responseArray[i * QUERY_NW_NUM_PARAMS + 2], numeric);

        free(s);

        /*
         * Check if modem returned an empty string, and fill it with MNC/MMC
         * if that's the case.
         */
        if (responseArray[i * QUERY_NW_NUM_PARAMS + 0] && strlen(responseArray[i * QUERY_NW_NUM_PARAMS + 0]) == 0) {
            responseArray[i * QUERY_NW_NUM_PARAMS + 0] = alloca(strlen(responseArray[i * QUERY_NW_NUM_PARAMS + 2]) + 1);
            strcpy(responseArray[i * QUERY_NW_NUM_PARAMS + 0], responseArray[i * QUERY_NW_NUM_PARAMS + 2]);
        }

        if (responseArray[i * QUERY_NW_NUM_PARAMS + 1] && strlen(responseArray[i * QUERY_NW_NUM_PARAMS + 1]) == 0) {
            responseArray[i * QUERY_NW_NUM_PARAMS + 1] = alloca(strlen(responseArray[i * QUERY_NW_NUM_PARAMS + 2]) + 1);
            strcpy(responseArray[i * QUERY_NW_NUM_PARAMS + 1], responseArray[i * QUERY_NW_NUM_PARAMS + 2]);
        }

       /* Add status */
        responseArray[i * QUERY_NW_NUM_PARAMS + 3] = alloca(strlen(statusTable[status]) + 1);
        sprintf(responseArray[i * QUERY_NW_NUM_PARAMS + 3], "%s", statusTable[status]);
    }

    RIL_onRequestComplete(t, RIL_E_SUCCESS, responseArray,
                          i * QUERY_NW_NUM_PARAMS * sizeof(char *));

finally:
    at_response_free(atresponse);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
/**
 * RIL_REQUEST_DATA_REGISTRATION_STATE
 *
 * Request current GPRS registration state.
 */
void requestGprsRegistrationState(int request, void *data,
                              size_t datalen, RIL_Token t)
{
    (void)request, (void)data, (void)datalen;
    int err = 0;
    const char resp_size = 6;
    int response[resp_size];
    char *responseStr[resp_size];
    ATResponse *atresponse = NULL;
    char *line, *p;
    int commas = 0;
    int skip, tmp;
    int count = 3;

    getScreenStateLock();
    if (!getScreenState())
        (void)at_send_command("AT+CGREG=2"); /* Response not vital */

    memset(responseStr, 0, sizeof(responseStr));
    memset(response, 0, sizeof(response));
    response[1] = -1;
    response[2] = -1;

    err = at_send_command_singleline("AT+CGREG?", "+CGREG: ", &atresponse);
    if (err != AT_NOERROR)
        goto error;

    line = atresponse->p_intermediates->line;
    err = at_tok_start(&line);
    if (err < 0)
        goto error;
    /*
     * The solicited version of the +CGREG response is
     * +CGREG: n, stat, [lac, cid [,<AcT>]]
     * and the unsolicited version is
     * +CGREG: stat, [lac, cid [,<AcT>]]
     * The <n> parameter is basically "is unsolicited creg on?"
     * which it should always be.
     *
     * Now we should normally get the solicited version here,
     * but the unsolicited version could have snuck in
     * so we have to handle both.
     *
     * Also since the LAC, CID and AcT are only reported when registered,
     * we can have 1, 2, 3, 4 or 5 arguments here.
     */
    /* Count number of commas */
    p = line;
    err = at_tok_charcounter(line, ',', &commas);
    if (err < 0) {
        LOGE("%s() at_tok_charcounter failed", __func__);
        goto error;
    }

    switch (commas) {
    case 0:                    /* +CGREG: <stat> */
        err = at_tok_nextint(&line, &response[0]);
        if (err < 0) goto error;
        break;

    case 1:                    /* +CGREG: <n>, <stat> */
        err = at_tok_nextint(&line, &skip);
        if (err < 0) goto error;
        err = at_tok_nextint(&line, &response[0]);
        if (err < 0) goto error;
        break;

    case 2:                    /* +CGREG: <stat>, <lac>, <cid> */
        err = at_tok_nextint(&line, &response[0]);
        if (err < 0) goto error;
        err = at_tok_nexthexint(&line, &response[1]);
        if (err < 0) goto error;
        err = at_tok_nexthexint(&line, &response[2]);
        if (err < 0) goto error;
        break;

    case 3:                    /* +CGREG: <n>, <stat>, <lac>, <cid> */
                               /* +CGREG: <stat>, <lac>, <cid>, <AcT> */
        err = at_tok_nextint(&line, &tmp);
        if (err < 0) goto error;

        /* We need to check if the second parameter is <lac> */
        if (*(line) == '"') {
            response[0] = tmp; /* <stat> */
            err = at_tok_nexthexint(&line, &response[1]); /* <lac> */
            if (err < 0) goto error;
            err = at_tok_nexthexint(&line, &response[2]); /* <cid> */
            if (err < 0) goto error;
            err = at_tok_nextint(&line, &response[3]); /* <AcT> */
            if (err < 0) goto error;
            count = 4;
        } else {
            err = at_tok_nextint(&line, &response[0]); /* <stat> */
            if (err < 0) goto error;
            err = at_tok_nexthexint(&line, &response[1]); /* <lac> */
            if (err < 0) goto error;
            err = at_tok_nexthexint(&line, &response[2]); /* <cid> */
            if (err < 0) goto error;
        }
        break;

    case 4:                    /* +CGREG: <n>, <stat>, <lac>, <cid>, <AcT> */
        err = at_tok_nextint(&line, &skip); /* <n> */
        if (err < 0) goto error;
        err = at_tok_nextint(&line, &response[0]); /* <stat> */
        if (err < 0) goto error;
        err = at_tok_nexthexint(&line, &response[1]); /* <lac> */
        if (err < 0) goto error;
        err = at_tok_nexthexint(&line, &response[2]); /* <cid> */
        if (err < 0) goto error;
        err = at_tok_nextint(&line, &response[3]); /* <AcT> */
        if (err < 0) goto error;
        count = 4;
        break;

    default:
        LOGE("%s() Invalid input", __func__);
        goto error;
    }
    if (response[0] == CGREG_STAT_REG_HOME_NET ||
        response[0] == CGREG_STAT_ROAMING)
        responseStr[3] = getNetworkType(response[3]);

    /* Converting to stringlist for Android */
    asprintf(&responseStr[0], "%d", response[0]); /* state */

    if (response[1] >= 0)
        asprintf(&responseStr[1], "%04x", response[1]); /* LAC */
    else
        responseStr[1] = NULL;

    if (response[2] >= 0)
        asprintf(&responseStr[2], "%08x", response[2]); /* CID */
    else
        responseStr[2] = NULL;

    responseStr[5] = "1";

    RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, resp_size * sizeof(char *));

finally:
    if (!getScreenState())
        (void)at_send_command("AT+CGREG=0");

    releaseScreenStateLock(); /* Important! */

    if (responseStr[0])
        free(responseStr[0]);
    if (responseStr[1])
        free(responseStr[1]);
    if (responseStr[2])
        free(responseStr[2]);
    if (responseStr[3])
        free(responseStr[3]);

    at_response_free(atresponse);
    return;

error:
    LOGE("%s Must never return an error when radio is on", __func__);
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
/**
 * RIL_UNSOL_SIM_REFRESH
 *
 * Indicate when SIM issue a REFRESH proactive command to applications.
 */
void onStkSimRefresh(const char *s)
{
    int commas = 0;
    char *line = NULL;
    char *tok = NULL;
    int i, skip;
    int err = -1;
    int response[2];

    /* *ESIMRF: <cmdnumber>,<type>[[,< fileid>,<pathid>][…]] */

    tok = line = strdup(s);

    err = at_tok_charcounter(tok, ',', &commas);
    if (err < 0)
        commas = 0;
    else
        commas -= 1;

    err = at_tok_start(&tok);
    if (err < 0)
        goto error;

    err = at_tok_nextint(&tok, &(s_refeshStatus.cmdNumber));
    if (err < 0)
        goto error;

    err = at_tok_nextint(&tok, &(s_refeshStatus.cmdQualifier));
    if (err < 0)
        goto error;

    switch(s_refeshStatus.cmdQualifier) {
    case SAT_SIM_INITIALIZATION_AND_FULL_FILE_CHANGE_NOTIFICATION:
    case SAT_SIM_INITIALIZATION_AND_FILE_CHANGE_NOTIFICATION:
    case SAT_SIM_INITIALIZATION:
    case SAT_NAA_APPLICATION_RESET:
        /* SIM initialized.  All files should be re-read. */
        response[0] = SIM_INIT;
        s_refeshStatus.Result = 3; /* success, EFs read */
        break;
    case SAT_FILE_CHANGE_NOTIFICATION:
        /* one or more files on SIM has been updated */
        response[0] = SIM_FILE_UPDATE;
        s_refeshStatus.Result = 3; /* success, EFs read */
        break;
    case SAT_SIM_RESET:
        /* SIM reset. All files should be re-read. */
        response[0] = SIM_RESET;
        break;
    case SAT_NAA_SESSION_RESET:
        /* one or more files on SIM has been updated */
        response[0] = SIM_FILE_UPDATE;
        s_refeshStatus.Result = 3; /* success, EFs read */
        break;
    case SAT_STEERING_OF_ROAMING:
       /* not set in Terminal Profile for Android, should never happen */
    default:
        goto error;
        break;
    }

    if (response[0] != SIM_FILE_UPDATE) {
        response[1] = 0;
        RIL_onUnsolicitedResponse(RIL_UNSOL_SIM_REFRESH,
                                  response, sizeof(response));
        goto finally;
    }

    for (i = 0; i < commas; i += 2) {
        err = at_tok_nextint(&tok, &(response[1]));
        if (err < 0) {
            /* check if response is already sent to Android */
            if (i > 0)
                goto finally;
            else
                goto error;
        }
        /* <pathid> is not used by Android */
        err = at_tok_nextint(&tok, &skip);
        if (err < 0) {
            /* check if response is already sent to Android */
            if (i > 0)
                goto finally;
            else
                goto error;
        }
        RIL_onUnsolicitedResponse(RIL_UNSOL_SIM_REFRESH,
                                  response, sizeof(response));
    }

finally:
#ifndef USE_U8500_RIL
    if (response[0] != SIM_RESET) {
        // AT commands cannot be sent from the at reader thread
        enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, sendRefreshTerminalResponse, NULL, NULL);
    }
#endif
    free(line);
    return;

error:
    ALOGE("%s: failed to parse %s, default to SIM_INITIALIZATION", __func__, s);
    if (s_refeshStatus.cmdNumber < 0)
        s_refeshStatus.cmdNumber = 1;
    if (s_refeshStatus.cmdQualifier < 0)
        s_refeshStatus.cmdQualifier = SAT_SIM_INITIALIZATION;
    if (s_refeshStatus.Result < 0)
        s_refeshStatus.Result = 2; /* command performed with missing information */
    response[0] = SIM_INIT;
    response[1] = 0;
    RIL_onUnsolicitedResponse(RIL_UNSOL_SIM_REFRESH,
                              response, sizeof(response));
    goto finally;
}
void onConnectionStateChanged(const char *s)
{
    int m_state = -1, m_cause = -1, err;
    int commas;

    err = at_tok_start((char **) &s);
    if (err < 0)
        return;

    /* Count number of commas */
    err = at_tok_charcounter((char *) s, ',', &commas);
    if (err < 0)
        return;

    err = at_tok_nextint((char **) &s, &m_state);
    if (err < 0 || m_state < E2NAP_ST_DISCONNECTED
            || m_state > E2NAP_ST_CONNECTED) {
        m_state = -1;
        return;
    }

    err = at_tok_nextint((char **) &s, &m_cause);
    /* The <cause> will only be indicated/considered when <state>
     * is disconnected */
    if (err < 0 || m_cause < E2NAP_C_SUCCESS || m_cause > E2NAP_C_MAXIMUM
            || m_state != E2NAP_ST_DISCONNECTED)
        m_cause = -1;

    if (commas == 3) {
        int m_state2 = -1, m_cause2 = -1;
        err = at_tok_nextint((char **) &s, &m_state2);
        if (err < 0 || m_state2 < E2NAP_ST_DISCONNECTED
                || m_state2 > E2NAP_ST_CONNECTED) {
            m_state = -1;
            return;
        }

        if (m_state2 == E2NAP_ST_DISCONNECTED) {
            err = at_tok_nextint((char **) &s, &m_cause2);
            if (err < 0 || m_cause2 < E2NAP_C_SUCCESS
                    || m_cause2 > E2NAP_C_MAXIMUM) {
                m_cause2 = -1;
            }
        }

        if ((err = pthread_mutex_lock(&s_e2nap_mutex)) != 0)
            LOGE("%s() failed to take e2nap mutex: %s", __func__,
                    strerror(err));

        if (m_state == E2NAP_ST_CONNECTING || m_state2 == E2NAP_ST_CONNECTING) {
            s_e2napState = E2NAP_ST_CONNECTING;
        } else if (m_state == E2NAP_ST_CONNECTED) {
            s_e2napCause = m_cause2;
            s_e2napState = E2NAP_ST_CONNECTED;
        } else if (m_state2 == E2NAP_ST_CONNECTED) {
            s_e2napCause = m_cause;
            s_e2napState = E2NAP_ST_CONNECTED;
        } else {
            s_e2napCause = m_cause;
            s_e2napState = E2NAP_ST_DISCONNECTED;
        }
        if ((err = pthread_mutex_unlock(&s_e2nap_mutex)) != 0)
            LOGE("%s() failed to release e2nap mutex: %s", __func__,
                    strerror(err));
    } else {
        if ((err = pthread_mutex_lock(&s_e2nap_mutex)) != 0)
            LOGE("%s() failed to take e2nap mutex: %s", __func__,
                    strerror(err));

        s_e2napState = m_state;
        s_e2napCause = m_cause;
        if ((err = pthread_mutex_unlock(&s_e2nap_mutex)) != 0)
            LOGE("%s() failed to release e2nap mutex: %s", __func__,
                    strerror(err));

    }

    LOGD("%s() %s", e2napStateToString(m_state), __func__);
    if (m_state != E2NAP_ST_CONNECTING)
        enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, onPDPContextListChanged, NULL,
                NULL);

    /* Make system request network information. This will allow RIL to report any new
     * technology made available from connection.
     */
    if (E2NAP_ST_CONNECTED == m_state)
        RIL_onUnsolicitedResponse(
                RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);

    mbm_check_error_cause();
}
static int parse_ip_information(char** addresses, char** gateways, char** dnses, in_addr_t* addr, in_addr_t* gateway)
{
    ATResponse* p_response = NULL;

    int err = -1;
    int number_of_entries = 0;
    int iterator = 0;
    int dnscnt = 0;
    char *intermediate_line = NULL;
    char *line_origin = NULL;

    *addresses = NULL;
    *gateways = NULL;
    *dnses = NULL;

    enum {
        IP = 1,
        GATEWAY,
        DNS
    };

    /* *E2IPCFG:
     *  (1,"10.155.68.129")(2,"10.155.68.131")(3,"80.251.192.244")(3,"80.251.192.245")
     */
    err = at_send_command_singleline("AT*E2IPCFG?", "*E2IPCFG:", &p_response);
    if (err != AT_NOERROR)
        return -1;

    err = at_tok_charcounter(p_response->p_intermediates->line, '(',
            &number_of_entries);
    if (err < 0 || number_of_entries == 0) {
        LOGE("%s() Syntax error. Could not parse output", __func__);
        goto error;
    }

    intermediate_line = p_response->p_intermediates->line;

    /* Loop and collect information */
    for (iterator = 0; iterator < number_of_entries; iterator++) {
        int stat = 0;
        char *line_tok = NULL;
        char *address = NULL;
        char *remaining_intermediate_line = NULL;
        char* tmp_pointer = NULL;

        line_origin = line_tok = getFirstElementValue(intermediate_line,
                "(", ")", &remaining_intermediate_line);
        intermediate_line = remaining_intermediate_line;

        if (line_tok == NULL) {
            LOGD("%s: No more connection info", __func__);
            break;
        }

        /* <stat> */
        err = at_tok_nextint(&line_tok, &stat);
        if (err < 0) {
            goto error;
        }

        /* <address> */
        err = at_tok_nextstr(&line_tok, &address);
        if (err < 0) {
            goto error;
        }

        switch (stat % 10) {
        case IP:
            if (!*addresses)
                *addresses = strdup(address);
            else {
                tmp_pointer = realloc(*addresses,
                        strlen(address) + strlen(*addresses) + 1);
                if (NULL == tmp_pointer) {
                    LOGE("%s() Failed to allocate memory for addresses", __func__);
                    goto error;
                }
                *addresses = tmp_pointer;
                sprintf(*addresses, "%s %s", *addresses, address);
            }
            LOGD("%s() IP Address: %s", __func__, address);
            if (inet_pton(AF_INET, address, addr) <= 0) {
                LOGE("%s() inet_pton() failed for %s!", __func__, address);
                goto error;
            }
            break;

        case GATEWAY:
            if (!*gateways)
                *gateways = strdup(address);
            else {
                tmp_pointer = realloc(*gateways,
                        strlen(address) + strlen(*gateways) + 1);
                if (NULL == tmp_pointer) {
                    LOGE("%s() Failed to allocate memory for gateways", __func__);
                    goto error;
                }
                *gateways = tmp_pointer;
                sprintf(*gateways, "%s %s", *gateways, address);
            }
            LOGD("%s() GW: %s", __func__, address);
            if (inet_pton(AF_INET, address, gateway) <= 0) {
                LOGE("%s() Failed inet_pton for gw %s!", __func__, address);
                goto error;
            }
            break;

        case DNS:
            dnscnt++;
            LOGD("%s() DNS%d: %s", __func__, dnscnt, address);
            if (dnscnt == 1)
                *dnses = strdup(address);
            else if (dnscnt == 2) {
                tmp_pointer = realloc(*dnses,
                        strlen(address) + strlen(*dnses) + 1);
                if (NULL == tmp_pointer) {
                    LOGE("%s() Failed to allocate memory for dnses", __func__);
                    goto error;
                }
                *dnses = tmp_pointer;
                sprintf(*dnses, "%s %s", *dnses, address);
            }
            break;
        }
        free(line_origin);
        line_origin = NULL;
    }

    at_response_free(p_response);
    return 0;

error:

    free(line_origin);
    free(*addresses);
    free(*gateways);
    free(*dnses);
    at_response_free(p_response);

    *gateways = NULL;
    *addresses = NULL;
    *dnses = NULL;
    return -1;
}
void onConnectionStateChanged(const char *s)
{
    int m_state = -1, m_cause = -1, err;
    int commas;

    err = at_tok_start((char **) &s);
    if (err < 0)
        return;

    /* Count number of commas */
    err = at_tok_charcounter((char *) s, ',', &commas);
    if (err < 0)
        return;

    err = at_tok_nextint((char **) &s, &m_state);
    if (err < 0 || m_state < E2NAP_STATE_DISCONNECTED
            || m_state > E2NAP_STATE_CONNECTING) {
        m_state = -1;
        return;
    }

    err = at_tok_nextint((char **) &s, &m_cause);
    /* The <cause> will only be indicated/considered when <state>
     * is disconnected */
    if (err < 0 || m_cause < E2NAP_CAUSE_SUCCESS || m_cause > E2NAP_CAUSE_MAXIMUM
            || m_state != E2NAP_STATE_DISCONNECTED)
        m_cause = -1;

    if (commas == 3) {
        int m_state2 = -1, m_cause2 = -1;
        err = at_tok_nextint((char **) &s, &m_state2);
        if (err < 0 || m_state2 < E2NAP_STATE_DISCONNECTED
                || m_state2 > E2NAP_STATE_CONNECTED) {
            m_state = -1;
            return;
        }

        if (m_state2 == E2NAP_STATE_DISCONNECTED) {
            err = at_tok_nextint((char **) &s, &m_cause2);
            if (err < 0 || m_cause2 < E2NAP_CAUSE_SUCCESS
                    || m_cause2 > E2NAP_CAUSE_MAXIMUM) {
                m_cause2 = -1;
            }
        }

        if ((err = pthread_mutex_lock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to take e2nap mutex: %s", __func__,
                    strerror(err));

        if (m_state == E2NAP_STATE_CONNECTING || m_state2 == E2NAP_STATE_CONNECTING) {
            s_e2napState = E2NAP_STATE_CONNECTING;
        } else if (m_state == E2NAP_STATE_CONNECTED) {
            s_e2napCause = m_cause2;
            s_e2napState = E2NAP_STATE_CONNECTED;
        } else if (m_state2 == E2NAP_STATE_CONNECTED) {
            s_e2napCause = m_cause;
            s_e2napState = E2NAP_STATE_CONNECTED;
        } else {
            s_e2napCause = m_cause;
            s_e2napState = E2NAP_STATE_DISCONNECTED;
        }
        if ((err = pthread_mutex_unlock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to release e2nap mutex: %s", __func__,
                    strerror(err));
    } else {
        if ((err = pthread_mutex_lock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to take e2nap mutex: %s", __func__,
                    strerror(err));

        s_e2napState = m_state;
        s_e2napCause = m_cause;
        if ((err = pthread_mutex_unlock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to release e2nap mutex: %s", __func__,
                    strerror(err));

    }

    mbm_check_error_cause();

    if (m_state == E2NAP_STATE_DISCONNECTED) {
        /* Bring down the interface as well. */
        if (!(ifc_init())) {
            ifc_down(ril_iface);
            ifc_close();
        } else
            ALOGE("%s() Failed to set up ifc!", __func__);
    }

    if ((m_state == E2NAP_STATE_DISCONNECTED) && (s_DeactCalled == 0)) {
        enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, onPDPContextListChanged, NULL,
                NULL);
    }
    s_DeactCalled = 0;
}