Beispiel #1
0
/*
 * Returns: 0 if FDN is not enabled
 *          1 if FDN is enabled
 */
static int isFdnEnabled(void)
{
    int err = -1;
    int status = 0;
    char *line = NULL;
    ATResponse *atresponse = NULL;

    err = at_send_command_multiline("AT+CLCK=\"FD\",2", "+CLCK:", &atresponse);
    if (err < 0 || atresponse->success == 0)
        goto finally;

    line = atresponse->p_intermediates->line;

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

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

    /* status = 1 means that FDN facility is active */
    if (status != 1)
        status = 0;

finally:
    at_response_free(atresponse);
    return status;
}
Beispiel #2
0
void requestHangupForegroundResumeBackground(void *data, size_t datalen, RIL_Token t)
{
	// 3GPP 22.030 6.5.5
	// "Releases all active calls (if any exist) and accepts
	//  the other (held or waiting) call."
	//at_send_command("AT+CHLD=1", NULL, CC_CHANNEL_CTX);
	at_send_command_multiline("AT+CHLD=1", "NO CARRIER", NULL, CC_CHANNEL_CTX);

	/* success or failure is ignored by the upper layer here.
	 * it will call GET_CURRENT_CALLS and determine success that way */
	RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
}
Beispiel #3
0
extern void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
{
	int err;
	ATResponse *p_response;
	ATLine *p_cur;
	int countCalls;
	int countValidCalls;
	RIL_Call *p_calls;
	RIL_Call **pp_calls;
	int i;
	int needRepoll = 0;

#ifdef WORKAROUND_ERRONEOUS_ANSWER
	int prevIncomingOrWaitingLine;

	prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
	s_incomingOrWaitingLine = -1;
#endif  /*WORKAROUND_ERRONEOUS_ANSWER*/

	err = at_send_command_multiline("AT+CLCC", "+CLCC:", &p_response, CC_CHANNEL_CTX);

	if (err != 0 || p_response->success == 0) {
		RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    at_response_free(p_response);		
		return;
	}

	/* count the calls */
	for (countCalls = 0, p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next)
		countCalls++;

	/* yes, there's an array of pointers and then an array of structures */

	pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
	p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
	memset(p_calls, 0, countCalls * sizeof(RIL_Call));

	/* init the pointer array */
	for (i = 0; i < countCalls; i++)
		pp_calls[i] = &(p_calls[i]);

	for (countValidCalls = 0, p_cur = p_response->p_intermediates
	     ; p_cur != NULL
	     ; p_cur = p_cur->p_next
	     ) {
		err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);

		if (err != 0)
			continue;

#ifdef  WORKAROUND_ERRONEOUS_ANSWER
		if (p_calls[countValidCalls].state == RIL_CALL_INCOMING || 
            p_calls[countValidCalls].state == RIL_CALL_WAITING) {
			s_incomingOrWaitingLine = p_calls[countValidCalls].index;
        }
#endif  /*WORKAROUND_ERRONEOUS_ANSWER*/

		if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE && 
            p_calls[countValidCalls].state != RIL_CALL_HOLDING) {
			needRepoll = 1;
        }

		countValidCalls++;
	}

#ifdef WORKAROUND_ERRONEOUS_ANSWER
	// Basically:
	// A call was incoming or waiting
	// Now it's marked as active
	// But we never answered it
	//
	// This is probably a bug, and the call will probably
	// disappear from the call list in the next poll
	if (prevIncomingOrWaitingLine >= 0
	    && s_incomingOrWaitingLine < 0
	    && s_expectAnswer == 0
	    ) {
		for (i = 0; i < countValidCalls; i++) {
			if (p_calls[i].index == prevIncomingOrWaitingLine && 
                p_calls[i].state == RIL_CALL_ACTIVE && 
                s_repollCallsCount < REPOLL_CALLS_COUNT_MAX) {
				LOGI("Hit WORKAROUND_ERRONOUS_ANSWER case. Repoll count: %d\n", s_repollCallsCount);
				s_repollCallsCount++;
				goto error;
			}
		}
	}

	s_expectAnswer = 0;
	s_repollCallsCount = 0;
#endif  /*WORKAROUND_ERRONEOUS_ANSWER*/

	RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls, countValidCalls * sizeof(RIL_Call *));

	at_response_free(p_response);
	return;
    
error:
	RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
	at_response_free(p_response);
}
/**
 * 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;
}
/**
 * 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_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;
}
void requestOrSendPDPContextList(RIL_Token *token)
{
    ATResponse *atresponse = NULL;
    RIL_Data_Call_Response_v6 response;
    int e2napState = getE2napState();
    int err;
    int cid;
    char *line, *apn, *type;
    char* addresses = NULL;
    char* dnses = NULL;
    char* gateways = NULL;
    in_addr_t addr;
    in_addr_t gateway;

    memset(&response, 0, sizeof(response));
    response.ifname = ril_iface;

    err = at_send_command_multiline("AT+CGDCONT?", "+CGDCONT:", &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, &cid);
    if (err < 0)
        goto error;

    response.cid = cid;

    if (e2napState == E2NAP_ST_CONNECTED)
        response.active = 1;

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

    response.type = alloca(strlen(type) + 1);
    strcpy(response.type, type);

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

    at_response_free(atresponse);
    atresponse = NULL;

    /* TODO: Check if we should check ip for a specific CID instead */
    if (parse_ip_information(&addresses, &gateways, &dnses, &addr, &gateway) < 0) {
           LOGE("%s() Failed to parse network interface data", __func__);
           goto error;
    }

    response.addresses = addresses;
    response.gateways = gateways;
    response.dnses = dnses;
    response.suggestedRetryTime = -1;

    if (token != NULL)
        RIL_onRequestComplete(*token, RIL_E_SUCCESS, &response,
                sizeof(RIL_Data_Call_Response_v6));
    else
        RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, &response,
                sizeof(RIL_Data_Call_Response_v6));

    free(addresses);
    free(gateways);
    free(dnses);

    return;

error:
    if (token != NULL)
        RIL_onRequestComplete(*token, RIL_E_GENERIC_FAILURE, NULL, 0);
    else
        RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, NULL, 0);

    at_response_free(atresponse);
}
Beispiel #9
0
void _requestOperatorWCDMA(void *data, size_t datalen, RIL_Token t)
{
	int err;
	int i;
	int skip;
	ATLine *p_cur;
	char *response[3];

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

	ATResponse *p_response = NULL;

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

	/* we expect 3 lines here:
	 * +COPS: 0,0,"T - Mobile"
	 * +COPS: 0,1,"TMO"
	 * +COPS: 0,2,"310170"
	 */

	if (err != 0) goto error;

	for (i = 0, p_cur = p_response->p_intermediates
			; p_cur != NULL
			; p_cur = p_cur->p_next, i++
	    ) {
		char *line = p_cur->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 != 3) {
		/* expect 3 lines exactly */
		goto error;
	}

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

	return;
error:
	LOGE("requestOperator must not return error when radio is on");
	RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
	at_response_free(p_response);
}
Beispiel #10
0
static void requestCallForward(RIL_CallForwardInfo *data, size_t datalen, RIL_Token t)
{
	ATResponse *p_response = NULL;
	ATLine *p_cur;
	int err;
	char *cmd;

	if (datalen != sizeof(*data))
		goto error;

	if (data->status == 2)
		asprintf(&cmd, "AT+CCFC=%d,%d",
				data->reason,
				data->status);
	else
		asprintf(&cmd, "AT+CCFC=%d,%d,\"%s\"",
				data->reason,
				data->status,
				data->number ? data->number : "");

	err = at_send_command_multiline (cmd, "+CCFC:", &p_response);
	free(cmd);

	if (err < 0)
		goto error;

	switch (at_get_cme_error(p_response)) {
		case CME_SUCCESS:
		case CME_ERROR_NON_CME:
			break;

		default:
			goto error;
	}

	if (data->status == 2 ) {
		RIL_CallForwardInfo **forwardList, *forwardPool;
		int forwardCount = 0;
		int validCount = 0;
		int i;

		for (p_cur = p_response->p_intermediates
				; p_cur != NULL
				; p_cur = p_cur->p_next, forwardCount++
		    );

		forwardList = (RIL_CallForwardInfo **)
			alloca(forwardCount * sizeof(RIL_CallForwardInfo *));

		forwardPool = (RIL_CallForwardInfo *)
			alloca(forwardCount * sizeof(RIL_CallForwardInfo));

		memset(forwardPool, 0, forwardCount * sizeof(RIL_CallForwardInfo));

		/* init the pointer array */
		for(i = 0; i < forwardCount ; i++)
			forwardList[i] = &(forwardPool[i]);

		for (p_cur = p_response->p_intermediates
				; p_cur != NULL
				; p_cur = p_cur->p_next
		    ) {
			err = forwardFromCCFCLine(p_cur->line, forwardList[validCount]);

			if (err == 0)
				validCount++;
		}

		RIL_onRequestComplete(t, RIL_E_SUCCESS,
				validCount ? forwardList : NULL,
				validCount * sizeof (RIL_CallForwardInfo *));
	} else
		RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);

done:
	at_response_free(p_response);
	return;

error:
	RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
	at_response_free(p_response);
}