/**
 * RIL_REQUEST_QUERY_FACILITY_LOCK
 *
 * Query the status of a facility lock state.
 */
void requestQueryFacilityLock(void *data, size_t datalen, RIL_Token t)
{
    int err, response;
    ATResponse *atresponse = NULL;
    char *line = NULL;
    char *facility_string = NULL;
    char *facility_password = NULL;
    char *facility_class = NULL;

    (void) datalen;

    if (datalen < 3 * sizeof(char **)) {
        ALOGE("%s() bad data length!", __func__);
        goto error;
    }

    facility_string = ((char **) data)[0];
    facility_password = ((char **) data)[1];
    facility_class = ((char **) data)[2];

    err = at_send_command_singleline("AT+CLCK=\"%s\",2,\"%s\",%s", "+CLCK:", &atresponse,
            facility_string, facility_password, facility_class);
    if (err != AT_NOERROR)
        goto error;

    line = atresponse->p_intermediates->line;

    err = at_tok_start(&line);

    if (err < 0)
        goto error;

    err = at_tok_nextint(&line, &response);

    if (err < 0)
        goto error;

    RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
    at_response_free(atresponse);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    at_response_free(atresponse);
}
Beispiel #2
0
void* onPgpsUrlReceived(void *data)
{
    GpsCtrlContext *context = get_gpsctrl_context();
    int err;
    int ignore;
    int id;
    char *url;
    char *cmd;
    char *line = (char *) data;

    err = at_tok_start(&line);
    if (err < 0) {
        MBMLOGE("%s error parsing data", __FUNCTION__);
        return NULL;
    }

    /* Ignore 1 integer from line */
    err = at_tok_nextint(&line, &ignore);
    if (err < 0) {
        MBMLOGE("%s error parsing data", __FUNCTION__);
        return NULL;
    }

    err = at_tok_nextint(&line, &id);
    if (err < 0) {
        MBMLOGE("%s error parsing data", __FUNCTION__);
        return NULL;
    }

    err = at_tok_nextstr(&line, &url);
    if (err < 0) {
        MBMLOGW("%s error parsing pgps url", __FUNCTION__);
        return NULL;
    }

    err = asprintf(&cmd, "%d\n%s", id, url);
    if (err < 0) {
        MBMLOGE("%s error allocating cmd string", __FUNCTION__);
        return NULL;
    }

    service_handler_send_message(CMD_DOWNLOAD_PGPS_DATA, cmd);

    return NULL;
}
/**
 * RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE
 *
 * Query current network selectin mode.
 */
void requestQueryNetworkSelectionMode(void *data, size_t datalen,
                                      RIL_Token t)
{
    (void) data; (void) datalen;
    int err;
    ATResponse *atresponse = NULL;
    int response = 0;
    char *line;

    err = at_send_command_singleline("AT+COPS?", "+COPS:", &atresponse);

    if (err != AT_NOERROR)
        goto error;

    line = atresponse->p_intermediates->line;

    err = at_tok_start(&line);

    if (err < 0)
        goto error;

    err = at_tok_nextint(&line, &response);

    if (err < 0)
        goto error;

    /*
     * Android accepts 0(automatic) and 1(manual).
     * Modem may return mode 4(Manual/automatic).
     * Convert it to 1(Manual) as android expects.
     */
    if (response == 4)
        response = 1;

    RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));

finally:
    at_response_free(atresponse);
    return;

error:
    LOGE("%s() Must never return error when radio is on", __func__);
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
void onNetworkStatusChanged(const char *s)
{
    int err;
    int skip;
    int cs_status, ps_status;
    int resp;
    char *line = NULL, *tok = NULL;

    cs_status = ps_status = 0;

    tok = line = strdup(s);
    if (tok == NULL)
        goto error;

    at_tok_start(&tok);

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

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

    err = at_tok_nextint(&tok, &ps_status);
    if (err < 0)
        goto error;

    resp = RIL_RESTRICTED_STATE_NONE;
    if (cs_status == E2REG_ACCESS_CLASS_BARRED)
        resp |= RIL_RESTRICTED_STATE_CS_ALL;
    if (ps_status == E2REG_ACCESS_CLASS_BARRED)
        resp |= RIL_RESTRICTED_STATE_PS_ALL;

    RIL_onUnsolicitedResponse(RIL_UNSOL_RESTRICTED_STATE_CHANGED,
                              &resp, sizeof(int *));

    /* If registered, poll signal strength for faster update of signal bar */
    if ((cs_status == E2REG_REGISTERED) || (ps_status == E2REG_REGISTERED))
        enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, pollSignalStrength, (void *)-1, NULL);

error:
    free(line);
}
Beispiel #5
0
static AT_Error at_get_error(const ATResponse *p_response)
{
    int ret;
    int err;
    char *p_cur;

    if (p_response == NULL)
        return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);

    if (p_response->success > 0) {
        return AT_NOERROR;
    }

    if (p_response->finalResponse == NULL)
        return AT_ERROR_INVALID_RESPONSE;


    if (isFinalResponseSuccess(p_response->finalResponse))
        return AT_NOERROR;

    p_cur = p_response->finalResponse;
    err = at_tok_start(&p_cur);
    if (err < 0)
        return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);

    err = at_tok_nextint(&p_cur, &ret);
    if (err < 0)
        return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);

    if(strStartsWith(p_response->finalResponse, "+CME ERROR:"))
        return merror(CME_ERROR, ret);
    else if (strStartsWith(p_response->finalResponse, "+CMS ERROR:"))
        return merror(CMS_ERROR, ret);
    else if (strStartsWith(p_response->finalResponse, "ERROR:"))
        return merror(GENERIC_ERROR, GENERIC_ERROR_RESPONSE);
    else if (strStartsWith(p_response->finalResponse, "+NO CARRIER:"))
        return merror(GENERIC_ERROR, GENERIC_NO_CARRIER_RESPONSE);
    else if (strStartsWith(p_response->finalResponse, "+NO ANSWER:"))
        return merror(GENERIC_ERROR, GENERIC_NO_ANSWER_RESPONSE);
    else if (strStartsWith(p_response->finalResponse, "+NO DIALTONE:"))
        return merror(GENERIC_ERROR, GENERIC_NO_DIALTONE_RESPONSE);
    else
        return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);
}
Beispiel #6
0
static int onMessageListing(char* s, char* sms_pdu)
{
	int*  index = malloc(sizeof(int));
	int stat = -1;
	char* line = NULL;
	line = strdup(s);
	at_tok_start(&line);
	at_tok_nextint(&line, index);
	at_tok_nextint(&line, &stat);
	RIL_requestTimedCallback (deleteMessageByIndex, index, NULL);

	if(stat == 0){
		RIL_onUnsolicitedResponse (
				RIL_UNSOL_RESPONSE_NEW_SMS,
				sms_pdu, strlen(sms_pdu));
	}
	free(line);
	return UNSOLICITED_SUCCESSED;
}
Beispiel #7
0
void _requestSignalStrengthWCDMA(void *data, size_t datalen, RIL_Token t)
{
	ATResponse *p_response = NULL;
	int err;
	RIL_SignalStrength_v6 resp;
	char *line;

	memset(&resp,0,sizeof(resp));

	err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);

	if (err < 0 || p_response->success == 0) {
		RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
		goto error;
	}

	line = p_response->p_intermediates->line;

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

	err = at_tok_nextint(&line, &(resp.GW_SignalStrength.signalStrength));
	if (err < 0) goto error;

	err = at_tok_nextint(&line, &(resp.GW_SignalStrength.bitErrorRate));
	if (err < 0) goto error;

	resp.LTE_SignalStrength.signalStrength = -1;
	resp.LTE_SignalStrength.rsrp = -1;
	resp.LTE_SignalStrength.rsrq = -1;
	resp.LTE_SignalStrength.rssnr = -1;
	resp.LTE_SignalStrength.cqi = -1;

	RIL_onRequestComplete(t, RIL_E_SUCCESS, &resp, sizeof(resp));

	at_response_free(p_response);
	return;

error:
	LOGE("requestSignalStrength must never return an error when radio is on");
	RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
	at_response_free(p_response);
}
Beispiel #8
0
static int getNetworkType()
{
	int err;
	ATResponse *p_response = NULL;
	int type = 0;
	char *line;

	err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);

	if (err < 0 || p_response->success == 0) {
		return type;
	}

	line = p_response->p_intermediates->line;

	err = at_tok_start(&line);

	if (err < 0) {
		goto out;
	}

	err = at_tok_nextint(&line, &type);
	err = at_tok_nextint(&line, &type);
	err = at_tok_nextint(&line, &type);
	err = at_tok_nextint(&line, &type);

	switch(type){
		case 0:
		case 1:
			type = 2;
			break;
		case 2:
			type = 3;
			break;
		default:
			type = 3;
			break;
	}
out:
	at_response_free(p_response);
	return type;	
}
/**
 * RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND
 *
 * Requests to send a SAT/USAT envelope command to SIM.
 * The SAT/USAT envelope command refers to 3GPP TS 11.14 and 3GPP TS 31.111.
 */
void requestStkSendEnvelopeCommand(void *data, size_t datalen, RIL_Token t)
{
    char *cmd;
    char *line;
    char *stkResponse;
    int err;
    ATResponse *atresponse = NULL;
    const char *ec = (const char *) data;

    asprintf(&cmd, "AT*STKE=\"%s\"", ec);
    err = at_send_command_singleline(cmd, "*STKE:", &atresponse);
    free(cmd);

    if (err < 0 || atresponse->success == 0)
        goto error;

    if (atresponse->p_intermediates) {
        line = atresponse->p_intermediates->line;

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

        err = at_tok_nextstr(&line, &stkResponse);
        if (err < 0)
            goto error;

        RIL_onRequestComplete(t, RIL_E_SUCCESS, stkResponse,
                              sizeof(char *));
    } else
        RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);

  finally:
    at_response_free(atresponse);

    return;

  error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
static int simIOSelectFile(unsigned short fileid)
{
    int err = 0;
    unsigned short lc = simIOGetLogicalChannel();
    ATResponse *atresponse = NULL;
    char *line;
    char *resp;
    int resplen;

    if (lc == 0)
        return -EIO;

    err = at_send_command_singleline("AT+CGLA=%d,14,\"00A4000C02%.4X\"", "+CGLA:", &atresponse, lc, fileid);
    if (at_get_error_type(err) == AT_ERROR)
        return err;
    if (err != AT_NOERROR)
        return -EINVAL;

    line = atresponse->p_intermediates->line;
    err = at_tok_start(&line);
    if (err < 0)
        goto finally;

    err = at_tok_nextint(&line, &resplen);
    if (err < 0)
        goto finally;

    err = at_tok_nextstr(&line, &resp);
    if (err < 0)
        goto finally;

    /* Std resp code: "9000" */
    if (resplen != 4 || strcmp(resp, "9000") != 0) {
        err = -EIO;
        goto finally;
    }

finally:
    at_response_free(atresponse);
    return err;
}
Beispiel #11
0
int eng_linuxcmd_atdiag(char *req, char *rsp)
{
    int len, ret;
    char tmp[3];
    char *data = req;
    char *ptr = NULL;

    ENG_LOG("Call %s", __FUNCTION__);

    if (strstr(req, "DEVT"))
        ret = test_dev(req, rsp);
    else {
        memset(g_buffer, 0, sizeof(g_buffer));
        at_tok_start(&data);
        at_tok_nextstr(&data, &ptr);

        len = eng_ascii2hex(ptr, g_buffer, strlen(ptr));
        ret = eng_atdiag_hdlr(g_buffer, len, rsp);
    }
    return ret;
}
void onStkEventNotify(const char *s)
{
    char *str;
    char *line;
    char *tok;
    int err;

    tok = line = strdup(s);

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

    err = at_tok_nextstr(&tok, &str);
    if (err < 0)
        goto error;

    RIL_onUnsolicitedResponse(RIL_UNSOL_STK_EVENT_NOTIFY, str,
                              sizeof(char *));

  error:
    free(line);
}
/**
 * RIL_UNSOL_STK_PROACTIVE_COMMAND
 *
 * Indicate when SIM issue a STK proactive command to applications.
 *
 */
void onStkProactiveCommand(const char *s)
{
    char *str;
    char *line;
    char *tok;
    int err;

    tok = line = strdup(s);

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

    err = at_tok_nextstr(&tok, &str);
    if (err < 0)
        goto error;

    RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND, str,
                              sizeof(char *));

  error:
    free(line);
}
/**
 * RIL_REQUEST_STK_GET_PROFILE
 *
 * Requests the profile of SIM tool kit.
 * The profile indicates the SAT/USAT features supported by ME.
 * The SAT/USAT features refer to 3GPP TS 11.14 and 3GPP TS 31.111.
 */
void requestStkGetProfile(void *data, size_t datalen, RIL_Token t)
{
    ATResponse *atresponse = NULL;
    char *line;
    char *response;
    int err = 0;
    int activated = 0;

    err = at_send_command_singleline("AT*STKC?", "*STKC:", &atresponse);
    if (err < 0 || atresponse->success == 0)
        goto error;

    line = atresponse->p_intermediates->line;

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

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

    err = at_tok_nextstr(&line, &response);
    if (err < 0)
        goto error;

    RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char *));

  finally:
    at_response_free(atresponse);

    return;

  error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
Beispiel #15
0
	/**
	 * RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE
	 *
	 * Query current network selectin mode.
	 ok
	 */
void requestQueryNetworkSelectionMode(
		void *data, size_t datalen, RIL_Token t)
{
	int err;
	ATResponse *p_response = NULL;
	int response = 0;
	char *line;


	err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);

	if (err < 0 || p_response->success == 0) {
		goto error;
	}

	line = p_response->p_intermediates->line;

	err = at_tok_start(&line);

	if (err < 0) {
		goto error;
	}

	err = at_tok_nextint(&line, &response);

	if (err < 0) {
		goto error;
	}

	RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
	at_response_free(p_response);
	return;
error:
	at_response_free(p_response);
	LOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
	RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
}
Beispiel #16
0
static int forwardFromCCFCLine(char *line, RIL_CallForwardInfo *p_forward)
{
	int err;
	int state;
	int mode;

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

	err = at_tok_nextint(&line, &(p_forward->status));
	if (err < 0) goto error;

	err = at_tok_nextint(&line, &(p_forward->serviceClass));
	if (err < 0) goto error;

	if (at_tok_hasmore(&line)) {
		err = at_tok_nextstr(&line, &(p_forward->number));

		/* tolerate null here */
		if (err < 0) return 0;

		if (p_forward->number != NULL
				&& 0 == strspn(p_forward->number, "+0123456789")
		   ) {
			p_forward->number = NULL;
		}

		err = at_tok_nextint(&line, &p_forward->toa);
		if (err < 0) goto error;
	}

	return 0;

error:
	LOGE("invalid CCFC line\n");
	return -1;
}
Beispiel #17
0
void onSuppServiceNotification(const char *s, int type)
{
	RIL_SuppSvcNotification ssnResponse;
	char *line;
	char *tok;
	int err;

	line = tok = strdup(s);

	memset(&ssnResponse, 0, sizeof(ssnResponse));
	ssnResponse.notificationType = type;

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

	err = at_tok_nextint(&tok, &ssnResponse.code);
	if (err < 0)
		goto error;

	if (ssnResponse.code == 16 || 
			(type == 0 && ssnResponse.code == 4) ||
			(type == 1 && ssnResponse.code == 1)) {
		err = at_tok_nextint(&tok, &ssnResponse.index);
		if (err < 0)
			goto error;
	}

	/* RIL_SuppSvcNotification has two more members that we won't
	   get from the +CSSI/+CSSU. Where do we get them, if we ever do? */

	RIL_onUnsolicitedResponse(RIL_UNSOL_SUPP_SVC_NOTIFICATION,
			&ssnResponse, sizeof(ssnResponse));

error:
	free(line);
}
Beispiel #18
0
void onNewSmsOnSIM(const char *s)
{
    char *line;
    char *mem;
    char *tok;
    int err = 0;
    int index = -1;

    tok = line = strdup(s);

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

    err = at_tok_nextstr(&tok, &mem);
    if (err < 0)
        goto error;

    if (strncmp(mem, "SM", 2) != 0)
        goto error;

    err = at_tok_nextint(&tok, &index);
    if (err < 0)
        goto error;

    RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM,
                              &index, sizeof(int *));

finally:
    free(line);
    return;

error:
    LOGE("Failed to parse +CMTI.");
    goto finally;
}
static char *getCharEncoding(void)
{
    int err;
    char *line, *chSet;
    char *result = NULL;
    ATResponse *p_response = NULL;
    err = at_send_command_singleline("AT+CSCS?", "+CSCS:", &p_response);

    if (err != AT_NOERROR) {
        LOGE("%s() Failed to read AT+CSCS?", __func__);
        return NULL;
    }

    line = p_response->p_intermediates->line;
    err = at_tok_start(&line);
    if (err < 0) {
        at_response_free(p_response);
        return NULL;
    }

    err = at_tok_nextstr(&line, &chSet);
    if (err < 0) {
        at_response_free(p_response);
        return NULL;
    }

    /* If not any of the listed below, assume UCS-2 */
    if (!strcmp(chSet, "GSM") || !strcmp(chSet, "IRA")
            || !strncmp(chSet, "8859", 4) || !strcmp(chSet, "UTF-8")) {
        result = strdup(chSet);
    } else
        result = strdup("UCS-2");

    at_response_free(p_response);
    return result;
}
Beispiel #20
0
/**  
 * RIL_REQUEST_GET_CLIR
 *
 * Gets current CLIR status.
 ok
 */
void requestGetCLIR(void *data, size_t datalen, RIL_Token t)
{
	ATResponse *p_response;
	p_response = NULL;
	int response[2] = {1, 1};

	int err = at_send_command_singleline("AT+CLIR?",
			"+CLIR: ", &p_response);
	if (err >= 0 && p_response->success) {
		char *line = p_response->p_intermediates->line;

		err = at_tok_start(&line);

		if (err >= 0) {
			err = at_tok_nextint(&line, &response[0]);

			if (err >= 0)
				err = at_tok_nextint(&line, &response[1]);
		}

	}
	RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
	at_response_free(p_response);
}
Beispiel #21
0
void onStkEventDownloadCall(char* urc, RILChannelCtx* p_channel)
{
    RIL_SOCKET_ID rid = getRILIdByChannelCtx(p_channel);

    int err, i = 0;
    char *p_cur = (char *)urc;
    int response[NUM_EVDL_CALL]={0};
    //RIL_EVDLCall response = NULL;

    /*
     * +EVDLCALL: <status>,<ti>,<is_mt_call>,<is_far_end>,<cause_len>,<cause>
     */
    for(i = 0; i < NUM_EVDL_CALL-1; i++) {
        response[i] = 0xff;
    }
    err = at_tok_start(&p_cur);
    if (err < 0) goto error;

    for(i = 0; i < NUM_EVDL_CALL-1; i++) {
        err = at_tok_nextint(&p_cur, &(response[i]));
        if(err < 0) { response[i] = 0xFF; LOGE("There is something wrong with item [%d]",i);}//goto error;
    }
    err = at_tok_nexthexint(&p_cur, &(response[i]));
    if(err < 0) {
        LOGE("There is something wrong with item [%d]",i);//goto error;
    }

    RIL_onUnsolicitedResponse(
            RIL_UNSOL_STK_EVDL_CALL,
            response, NUM_EVDL_CALL * sizeof(int),
            rid);

    return;
error:
    LOGE("There is something wrong with the +EVDLCALL");
}
char *getNetworkType(int def){
    int network = def;
    int err;
    int gsm_rinfo, umts_rinfo, skip;
    int ul, dl;
    int networkType;
    char *line;
    ATResponse *p_response;

    err = at_send_command_singleline("AT*ERINFO?", "*ERINFO:",
                                     &p_response);

    if (err != AT_NOERROR)
        return NULL;

    line = p_response->p_intermediates->line;
    err = at_tok_start(&line);
    if (err < 0)
            goto finally;

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

    err = at_tok_nextint(&line, &gsm_rinfo);
    if (err < 0)
            goto finally;

    err = at_tok_nextint(&line, &umts_rinfo);
    if (err < 0)
            goto finally;

    at_response_free(p_response);

    if (umts_rinfo > ERINFO_UMTS_NO_UMTS_HSDPA && getE2napState() == E2NAP_ST_CONNECTED) {

        err = at_send_command_singleline("AT+CGEQNEG=%d", "+CGEQNEG:", &p_response, RIL_CID_IP);

        if (err != AT_NOERROR)
            LOGE("%s() Allocation for, or sending, CGEQNEG failed."
	         "Using default value specified by calling function", __func__);
        else {
            line = p_response->p_intermediates->line;
            err = at_tok_start(&line);
            if (err < 0)
                goto finally;

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

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

            err = at_tok_nextint(&line, &ul);
            if (err < 0)
                goto finally;

            err = at_tok_nextint(&line, &dl);
            if (err < 0)
                goto finally;

            at_response_free(p_response);
            LOGI("Max speed %i/%i, UL/DL", ul, dl);

            network = CGREG_ACT_UTRAN;
            if (dl > 384)
                network = CGREG_ACT_UTRAN_HSDPA;
            if (ul > 384)
                network = CGREG_ACT_UTRAN_HSUPA_HSDPA;
            if (dl > 14400)
                network = CGREG_ACT_UTRAN_HSPAP;
        }
    }
    else if (gsm_rinfo) {
        LOGD("%s() Using 2G info: %d", __func__, gsm_rinfo);
        if (gsm_rinfo == 1)
            network = CGREG_ACT_GSM;
        else
            network = CGREG_ACT_GSM_EGPRS;
    }

    switch (network) {
    case CGREG_ACT_GSM:
        networkType = RADIO_TECH_GPRS;
        break;
    case CGREG_ACT_UTRAN:
        networkType = RADIO_TECH_UMTS;
        break;
    case CGREG_ACT_GSM_EGPRS:
        networkType = RADIO_TECH_EDGE;
        break;
    case CGREG_ACT_UTRAN_HSDPA:
        networkType = RADIO_TECH_HSDPA;
        break;
    case CGREG_ACT_UTRAN_HSUPA:
        networkType = RADIO_TECH_HSUPA; /* Note: Not used */
        break;
    case CGREG_ACT_UTRAN_HSUPA_HSDPA:
        networkType = RADIO_TECH_HSPA;
        break;
    case CGREG_ACT_UTRAN_HSPAP:
        networkType = RADIO_TECH_HSPAP;
        break;
    default:
        networkType = RADIO_TECH_UNKNOWN;
        break;
    }
    char *resp;
    asprintf(&resp, "%d", networkType);
    return resp;

finally:
    at_response_free(p_response);
    return NULL;
}
Beispiel #23
0
void requestLastCallFailCause(void *data, size_t datalen, RIL_Token t)
{
	/* MTK proprietary start */
	int callFailCause;
	char *line;
	int ret;
	ATResponse *p_response = NULL;

	//Solve [ALPS00242104]Invalid number show but cannot call drop when dial VT call in 2G network
	//mtk04070, 2012.02.24
	if (bUseLocalCallFailCause == 1) {
	   callFailCause = dialLastError;
	   LOGD("Use local call fail cause = %d", callFailCause);
	}
	else {
 	   ret = at_send_command_singleline("AT+CEER", "+CEER:", &p_response, CC_CHANNEL_CTX);

	   if (ret < 0 || p_response->success == 0)
		   goto error;

	   line = p_response->p_intermediates->line;

	   ret = at_tok_start(&line);

	   if (ret < 0)
		   goto error;

	   ret = at_tok_nextint(&line, &callFailCause);

	   if (ret < 0)
		   goto error;

	   LOGD("MD fail cause = %d", callFailCause);
	}

	/*if there are more causes need to be translated in the future,
	 * discussing with APP owner to implement this in upper layer.
	 * For the hard coded value, please refer to modem code.*/

	if (callFailCause == 10 || callFailCause == 8)
		callFailCause = CALL_FAIL_CALL_BARRED;
	else if (callFailCause == 2600)
		callFailCause = CALL_FAIL_FDN_BLOCKED;
	else if (callFailCause == 2052)
		callFailCause = CALL_FAIL_IMSI_UNKNOWN_IN_VLR;
	else if (callFailCause == 2053)
		callFailCause = CALL_FAIL_IMEI_NOT_ACCEPTED;
	else if ((callFailCause > 127 && callFailCause != 2165) || callFailCause <= 0)
		callFailCause = CALL_FAIL_ERROR_UNSPECIFIED;

	LOGD("RIL fail cause = %d", callFailCause);
	RIL_onRequestComplete(t, RIL_E_SUCCESS, &callFailCause, sizeof(int));
	if (NULL != p_response) 
	{
		at_response_free(p_response);
	}
	return;

error:
	RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
	if (NULL != p_response) 
	{
	    at_response_free(p_response);
	}
	/* MTK proprietary end */
}
/**
 * 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_SET_NETWORK_SELECTION_AUTOMATIC
 *
 * Specify that the network should be selected automatically.
*/
void requestSetNetworkSelectionAutomatic(void *data, size_t datalen,
                                         RIL_Token t)
{
    (void) data; (void) datalen;
    int err = 0;
    ATResponse *atresponse = NULL;
    int mode = 0;
    int skip;
    char *line;
    char *operator = NULL;
    struct operatorPollParams *poll_params = NULL;

    poll_params = malloc(sizeof(struct operatorPollParams));
    if (NULL == poll_params)
        goto error;

    /* First check if we are already scanning or in manual mode */
    err = at_send_command_singleline("AT+COPS=3,2;+COPS?", "+COPS:", &atresponse);
    if (err != AT_NOERROR)
        goto error;

    line = atresponse->p_intermediates->line;

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

    /* Read network selection mode */
    err = at_tok_nextint(&line, &mode);
    if (err < 0)
        goto error;

    /* If we're unregistered, we may just get
       a "+COPS: 0" response. */
    if (!at_tok_hasmore(&line)) {
        if (mode == 1) {
            LOGD("%s() Changing manual to automatic network mode", __func__);
            goto do_auto;
        } else
            goto check_reg;
    }

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

    /* A "+COPS: 0, n" response is also possible. */
    if (!at_tok_hasmore(&line)) {
        if (mode == 1) {
            LOGD("%s() Changing manual to automatic network mode", __func__);
            goto do_auto;
        } else
            goto check_reg;
    }

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

    /* If operator is found then do a new scan,
       else let it continue the already pending scan */
    if (operator && strlen(operator) == 0) {
        if (mode == 1) {
            LOGD("%s() Changing manual to automatic network mode", __func__);
            goto do_auto;
        } else
            goto check_reg;
    }

    /* Operator found */
    if (mode == 1) {
        LOGD("%s() Changing manual to automatic network mode", __func__);
        goto do_auto;
    } else {
        LOGD("%s() Already in automatic mode with known operator, trigger a new network scan",
	    __func__);
        goto do_auto;
    }

    /* Check if module is scanning,
       if not then trigger a rescan */
check_reg:
    at_response_free(atresponse);
    atresponse = NULL;

    /* Check CS domain first */
    err = at_send_command_singleline("AT+CREG?", "+CREG:", &atresponse);
    if (err != AT_NOERROR)
        goto error;

    line = atresponse->p_intermediates->line;

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

    /* Read registration unsolicited mode */
    err = at_tok_nextint(&line, &mode);
    if (err < 0)
        goto error;

    /* Read registration status */
    err = at_tok_nextint(&line, &mode);
    if (err < 0)
        goto error;

    /* If scanning has stopped, then perform a new scan */
    if (mode == 0) {
        LOGD("%s() Already in automatic mode, but not currently scanning on CS,"
	     "trigger a new network scan", __func__);
        goto do_auto;
    }

    /* Now check PS domain */
    at_response_free(atresponse);
    atresponse = NULL;
    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;

    /* Read registration unsolicited mode */
    err = at_tok_nextint(&line, &mode);
    if (err < 0)
        goto error;

    /* Read registration status */
    err = at_tok_nextint(&line, &mode);
    if (err < 0)
        goto error;

    /* If scanning has stopped, then perform a new scan */
    if (mode == 0) {
        LOGD("%s() Already in automatic mode, but not currently scanning on PS,"
	     "trigger a new network scan", __func__);
        goto do_auto;
    }
    else
    {
        LOGD("%s() Already in automatic mode and scanning", __func__);
        goto finish_scan;
    }

do_auto:
    at_response_free(atresponse);
    atresponse = NULL;

    /* This command does two things, one it sets automatic mode,
       two it starts a new network scan! */
    err = at_send_command("AT+COPS=0");
    if (err != AT_NOERROR)
        goto error;

finish_scan:

    at_response_free(atresponse);
    atresponse = NULL;

    poll_params->loopcount = 0;
    poll_params->t = t;

    enqueueRILEvent(RIL_EVENT_QUEUE_NORMAL, pollOperatorSelected,
                    poll_params, &TIMEVAL_OPERATOR_SELECT_POLL);

    return;

error:
    free(poll_params);
    at_response_free(atresponse);
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    return;
}
int getSignalStrength(RIL_SignalStrength_v6 *signalStrength){
    ATResponse *atresponse = NULL;
    int err;
    char *line;
    int ber;
    int rssi;

    memset(signalStrength, 0, sizeof(RIL_SignalStrength_v6));

    signalStrength->LTE_SignalStrength.signalStrength = -1;
    signalStrength->LTE_SignalStrength.rsrp = -1;
    signalStrength->LTE_SignalStrength.rsrq = -1;
    signalStrength->LTE_SignalStrength.rssnr = -1;
    signalStrength->LTE_SignalStrength.cqi = -1;

    err = at_send_command_singleline("AT+CSQ", "+CSQ:", &atresponse);

    if (err != AT_NOERROR)
        goto cind;
    
    line = atresponse->p_intermediates->line;

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

    err = at_tok_nextint(&line,&rssi);
    if (err < 0)
        goto cind;
    signalStrength->GW_SignalStrength.signalStrength = rssi;

    err = at_tok_nextint(&line, &ber);
    if (err < 0)
        goto cind;
    signalStrength->GW_SignalStrength.bitErrorRate = ber;

    at_response_free(atresponse);
    atresponse = NULL;
    /*
     * If we get 99 as signal strength. Try AT+CIND to give
     * some indication on what signal strength we got.
     *
     * Android calculates rssi and dBm values from this value, so the dBm
     * value presented in android will be wrong, but this is an error on
     * android's end.
     */
    if (rssi == 99) {
cind:
        at_response_free(atresponse);
        atresponse = NULL;

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

        line = atresponse->p_intermediates->line;

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

        /* discard the first value */
        err = at_tok_nextint(&line,
                             &signalStrength->GW_SignalStrength.signalStrength);
        if (err < 0)
            goto error;

        err = at_tok_nextint(&line,
                             &signalStrength->GW_SignalStrength.signalStrength);
        if (err < 0)
            goto error;

        signalStrength->GW_SignalStrength.bitErrorRate = 99;

        /* Convert CIND value so Android understands it correctly */
        if (signalStrength->GW_SignalStrength.signalStrength > 0) {
            signalStrength->GW_SignalStrength.signalStrength *= 4;
            signalStrength->GW_SignalStrength.signalStrength--;
        }
    }

    at_response_free(atresponse);
    return 0;

error:
    at_response_free(atresponse);
    return -1;
}
/**
 * WCDMA Network (UTMS, 3G) Neighborhood Cell IDs
 */
void Get_WCDMA_NCIs(RIL_Token t)
{
    int err = 0;
    char *p = NULL;
    int n = 0;
    ATLine *tmp = NULL;
    ATResponse *wnci_resp = NULL;
    RIL_NeighboringCell *ptr_cells[MAX_NUM_NEIGHBOR_CELLS];

    err = at_send_command_multiline("AT*EWNCI", "*EWNCI:", &wnci_resp);
    if (err < 0 || wnci_resp->success == 0)
        goto error;

    tmp = wnci_resp->p_intermediates;
    while (tmp) {
        if (n > MAX_NUM_NEIGHBOR_CELLS)
            goto error;
        p = tmp->line;
        if (*p == '*') {
            char *line = p;
            int uarfcn = 0;
            int psc = 0;
            int rscp = 0;
            int ecno = 0;
            int pathloss = 0;

            err = at_tok_start(&line);
            if (err < 0) goto error;
            /* UARFCN */
            err = at_tok_nextint(&line, &uarfcn);
            if (err < 0) goto error;
            /* PSC */
            err = at_tok_nextint(&line, &psc);
            if (err < 0) goto error;
            /* RSCP */
            err = at_tok_nextint(&line, &rscp);
            if (err < 0) goto error;
            /* ECNO */
            err = at_tok_nextint(&line, &ecno);
            if (err < 0) goto error;
            /* PathLoss */
            err = at_tok_nextint(&line, &pathloss);
            if (err < 0) goto error;

            /* process data for each cell */
            ptr_cells[n] = alloca(sizeof(RIL_NeighboringCell));
            ptr_cells[n]->rssi = rscp;
            ptr_cells[n]->cid = alloca(9 * sizeof(char));
            sprintf(ptr_cells[n]->cid, "%08x", psc);
            n++;
        }
        tmp = tmp->p_next;
    }

    RIL_onRequestComplete(t, RIL_E_SUCCESS, ptr_cells,
                          n * sizeof(RIL_NeighboringCell *));

finally:
    at_response_free(wnci_resp);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
/**
 * GSM Network (GPRS, 2G) Neighborhood Cell IDs
 */
void Get_GSM_NCIs(RIL_Token t)
{
    int err = 0;
    char *p = NULL;
    int n = 0;
    ATLine *tmp = NULL;
    ATResponse *gnci_resp = NULL;
    RIL_NeighboringCell *ptr_cells[MAX_NUM_NEIGHBOR_CELLS];

    err = at_send_command_multiline("AT*EGNCI", "*EGNCI:", &gnci_resp);
    if (err < 0 ||
        gnci_resp->success == 0 || gnci_resp->p_intermediates == NULL)
        goto error;

    tmp = gnci_resp->p_intermediates;
    while (tmp) {
        if (n > MAX_NUM_NEIGHBOR_CELLS)
            goto error;
        p = tmp->line;
        if (*p == '*') {
            char *line = p;
            char *plmn = NULL;
            char *lac = NULL;
            char *cid = NULL;
            int arfcn = 0;
            int bsic = 0;
            int rxlvl = 0;
            int ilac = 0;
            int icid = 0;

            err = at_tok_start(&line);
            if (err < 0) goto error;
            /* PLMN */
            err = at_tok_nextstr(&line, &plmn);
            if (err < 0) goto error;
            /* LAC */
            err = at_tok_nextstr(&line, &lac);
            if (err < 0) goto error;
            /* CellID */
            err = at_tok_nextstr(&line, &cid);
            if (err < 0) goto error;
            /* ARFCN */
            err = at_tok_nextint(&line, &arfcn);
            if (err < 0) goto error;
            /* BSIC */
            err = at_tok_nextint(&line, &bsic);
            if (err < 0) goto error;
            /* RxLevel */
            err = at_tok_nextint(&line, &rxlvl);
            if (err < 0) goto error;

            /* process data for each cell */
            ptr_cells[n] = alloca(sizeof(RIL_NeighboringCell));
            ptr_cells[n]->rssi = rxlvl;
            ptr_cells[n]->cid = alloca(9 * sizeof(char));
            sscanf(lac,"%x",&ilac);
            sscanf(cid,"%x",&icid);
            sprintf(ptr_cells[n]->cid, "%08x", ((ilac << 16) + icid));
            n++;
        }
        tmp = tmp->p_next;
    }

    RIL_onRequestComplete(t, RIL_E_SUCCESS, ptr_cells,
                          n * sizeof(RIL_NeighboringCell *));

finally:
    at_response_free(gnci_resp);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
/**
 * RIL_REQUEST_NEIGHBORINGCELL_IDS
 */
void requestNeighboringCellIDs(void *data, size_t datalen, RIL_Token t)
{
    (void) data; (void) datalen;
    int network = -1;
    int dummy = 0;
    char *dummyStr = NULL;
    int err = 0;
    ATResponse *cops_resp = NULL;
    char *line = NULL;

    /* Determine network radio access technology (AcT) */
    err = at_send_command_singleline("AT+COPS?", "+COPS:", &cops_resp);
    if (err < 0 || cops_resp->success == 0) goto error;

    line = cops_resp->p_intermediates->line;

    err = at_tok_start(&line);
    if (err < 0) goto error;
    /* Mode */
    err = at_tok_nextint(&line, &dummy);
    if (err < 0) goto error;
    /* Check to see if not registered */
    if (!at_tok_hasmore(&line)) {
        No_NCIs(t);
        goto finally;
    }
    /* Format */
    err = at_tok_nextint(&line, &dummy);
    if (err < 0) goto error;
    /* Operator */
    err = at_tok_nextstr(&line, &dummyStr);
    if (err < 0) goto error;
    /* Network */
    err = at_tok_nextint(&line, &network);
    if (err < 0) goto error;

    switch (network) {
    case 0:                    /* GSM (GPRS,2G)*/
    case 3:                    /* GSM w/EGPRS (EDGE, 2.75G)*/
        Get_GSM_NCIs(t);
        break;
    case 1:                    /* GSM Compact (Not supported)*/
        goto error;
        break;
    case 2:                    /* UTRAN (WCDMA/UMTS, 3G)*/
    case 4:                    /* UTRAN w/HSDPA (HSDPA,3G)*/
    case 5:                    /* UTRAN w/HSUPA (HSUPA,3G)*/
    case 6:                    /* UTRAN w/HSDPA and HSUPA (HSPA,3G)*/
        Get_WCDMA_NCIs(t);
        break;
    default:
        goto error;
    }

finally:
    at_response_free(cops_resp);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}
/**
 * RIL_REQUEST_OPERATOR
 *
 * Request current operator ONS or EONS.
 */
void requestOperator(void *data, size_t datalen, RIL_Token t)
{
    (void) data; (void) datalen;
    int err;
    int i;
    int skip;
    ATLine *cursor;
    static const int num_resp_lines = 3;
    char *response[num_resp_lines];
    ATResponse *atresponse = NULL;

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

    err = at_send_command_multiline
        ("AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", "+COPS:",
         &atresponse);

    if (err != AT_NOERROR)
        goto error;

    /* We expect 3 lines here:
     * +COPS: 0,0,"T - Mobile"
     * +COPS: 0,1,"TMO"
     * +COPS: 0,2,"310170"
     */
    for (i = 0, cursor = atresponse->p_intermediates;
         cursor != NULL && i < num_resp_lines;
         cursor = cursor->p_next, i++) {
        char *line = cursor->line;

        err = at_tok_start(&line);

        if (err < 0)
            goto error;

        err = at_tok_nextint(&line, &skip);

        if (err < 0)
            goto error;

        /* If we're unregistered, we may just get
           a "+COPS: 0" response. */
        if (!at_tok_hasmore(&line)) {
            response[i] = NULL;
            continue;
        }

        err = at_tok_nextint(&line, &skip);

        if (err < 0)
            goto error;

        /* A "+COPS: 0, n" response is also possible. */
        if (!at_tok_hasmore(&line)) {
            response[i] = NULL;
            continue;
        }

        err = at_tok_nextstr(&line, &(response[i]));

        if (err < 0)
            goto error;
    }

    if (i != num_resp_lines)
        goto error;

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

    if (response[2] && response[1] && strlen(response[1]) == 0) {
        response[1] = alloca(strlen(response[2]) + 1);
        strcpy(response[1], response[2]);
    }

    RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));

finally:
    at_response_free(atresponse);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    goto finally;
}