/* * 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; }
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); }
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); }
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); }
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); }