/** * Poll +COPS? and return a success, or if the loop counter reaches * REPOLL_OPERATOR_SELECTED, return generic failure. */ static void pollOperatorSelected(void *params) { int err = 0; int response = 0; char *line = NULL; ATResponse *atresponse = NULL; struct operatorPollParams *poll_params; RIL_Token t; assert(params != NULL); poll_params = (struct operatorPollParams *) params; t = poll_params->t; if (poll_params->loopcount >= REPOLL_OPERATOR_SELECTED) goto error; 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; /* If we don't get more than the COPS: {0-4} we are not registered. Loop and try again. */ if (!at_tok_hasmore(&line)) { switch (s_registrationDeniedReason) { case IMSI_UNKNOWN_IN_HLR: /* fall through */ case ILLEGAL_ME: RIL_onRequestComplete(t, RIL_E_ILLEGAL_SIM_OR_ME, NULL, 0); free(poll_params); break; default: poll_params->loopcount++; enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, pollOperatorSelected, poll_params, &TIMEVAL_OPERATOR_SELECT_POLL); } } else { /* We got operator, throw a success! */ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); free(poll_params); } at_response_free(atresponse); return; error: RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); free(poll_params); at_response_free(atresponse); return; }
int sendSimIOCmdICC(const RIL_SIM_IO_v6 *ioargs, ATResponse **atresponse, RIL_SIM_IO_Response *sr) { int err; char *fmt; char *arg6; char *arg7; char *line; /* FIXME Handle pin2. */ memset(sr, 0, sizeof(*sr)); arg6 = ioargs->data; arg7 = ioargs->path; if (arg7 && arg6) { fmt = "AT+CRSM=%d,%d,%d,%d,%d,\"%s\",\"%s\""; } else if (arg7) { fmt = "AT+CRSM=%d,%d,%d,%d,%d,,\"%s\""; arg6 = arg7; } else if (arg6) { fmt = "AT+CRSM=%d,%d,%d,%d,%d,\"%s\""; } else { fmt = "AT+CRSM=%d,%d,%d,%d,%d"; } err = at_send_command_singleline(fmt, "+CRSM:", atresponse,ioargs->command, ioargs->fileid, ioargs->p1, ioargs->p2, ioargs->p3, arg6, arg7); if (err != AT_NOERROR) return err; line = (*atresponse)->p_intermediates->line; err = at_tok_start(&line); if (err < 0) goto finally; err = at_tok_nextint(&line, &(sr->sw1)); if (err < 0) goto finally; err = at_tok_nextint(&line, &(sr->sw2)); if (err < 0) goto finally; if (at_tok_hasmore(&line)) { err = at_tok_nextstr(&line, &(sr->simResponse)); if (err < 0) goto finally; } finally: return err; }
/** * Note: directly modified line and has *p_call point directly into * modified line */ static int callFromCLCCLine(char *line, RIL_Call *p_call) { //+CLCC: 1,0,2,0,0,\"+18005551212\",145 // index,isMT,state,mode,isMpty(,number,TOA)? int err; int state; int mode; err = at_tok_start(&line); if (err < 0) goto error; err = at_tok_nextint(&line, &(p_call->index)); if (err < 0) goto error; err = at_tok_nextbool(&line, &(p_call->isMT)); if (err < 0) goto error; err = at_tok_nextint(&line, &state); if (err < 0) goto error; err = clccStateToRILState(state, &(p_call->state)); if (err < 0) goto error; err = at_tok_nextint(&line, &mode); if (err < 0) goto error; p_call->isVoice = (mode == 0); err = at_tok_nextbool(&line, &(p_call->isMpty)); if (err < 0) goto error; if (at_tok_hasmore(&line)) { err = at_tok_nextstr(&line, &(p_call->number)); /* tolerate null here */ if (err < 0) return 0; // Some lame implementations return strings // like "NOT AVAILABLE" in the CLCC line if (p_call->number != NULL && 0 == strspn(p_call->number, "+0123456789")) p_call->number = NULL; err = at_tok_nextint(&line, &p_call->toa); if (err < 0) goto error; } p_call->uusInfo = NULL; return 0; error: LOGE("invalid CLCC line\n"); return -1; }
/** * RIL_UNSOL_ON_USSD * * Called when a new USSD message is received. */ int onUSSDReceived(const char *s, char* sms_pdu) { char *line, *linestart; int typeCode, count, err, len; char *message; char *outputmessage; char *responseStr[2]; linestart=line=strdup(s); err = at_tok_start(&line); if(err < 0) goto out; err = at_tok_nextint(&line, &typeCode); if(err < 0) goto out; if(at_tok_hasmore(&line)) { int format; char message[256]; int n = sscanf(s+6,"%*d,\"%[^\"]\",%d",message,&format); LOGD("%s,%d",message,format); if(format == 15){ responseStr[1] = malloc(strlen(message)+1); strcpy(responseStr[1],message); }else{ int len = strlen(message); outputmessage = malloc(len/2); gsm_hex_to_bytes((cbytes_t)message,len,(bytes_t)outputmessage); responseStr[1] = malloc(len); len = ucs2_to_utf8((cbytes_t)outputmessage,len/2,(bytes_t)responseStr[1]); free(outputmessage); } count = 2; } else { responseStr[1]=NULL; count = 1; } free(linestart); asprintf(&responseStr[0], "%d", typeCode); RIL_onUnsolicitedResponse (RIL_UNSOL_ON_USSD, responseStr, count*sizeof(char*)); out: return UNSOLICITED_SUCCESSED; }
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; }
/** * 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; }
/** * 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; }
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); }