/** * SIM ready means any commands that access the SIM will work, including: * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM * (all SMS-related commands). */ void pollSIMState(void *param) { if (((int) param) != 1 && getRadioState() != RADIO_STATE_SIM_NOT_READY && getRadioState() != RADIO_STATE_SIM_LOCKED_OR_ABSENT) /* No longer valid to poll. */ return; switch (getSIMStatus()) { case SIM_NOT_READY: ALOGI("SIM_NOT_READY, poll for sim state."); enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, pollSIMState, NULL, &TIMEVAL_SIMPOLL); return; case SIM_PIN2: case SIM_PUK2: case SIM_PUK2_PERM_BLOCKED: case SIM_READY: setRadioState(RADIO_STATE_SIM_READY); enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, setPollSIMState, (void *) 1, NULL); return; case SIM_ABSENT: setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT); enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, setPollSIMState, (void *) 0, NULL); return; case SIM_PIN: case SIM_PUK: case SIM_NETWORK_PERSO: case SIM_NETWORK_SUBSET_PERSO: case SIM_SERVICE_PROVIDER_PERSO: case SIM_CORPORATE_PERSO: case SIM_SIM_PERSO: case SIM_STERICSSON_LOCK: case SIM_BLOCKED: case SIM_PERM_BLOCKED: case SIM_NETWORK_PERSO_PUK: case SIM_NETWORK_SUBSET_PERSO_PUK: case SIM_SERVICE_PROVIDER_PERSO_PUK: case SIM_CORPORATE_PERSO_PUK: /* pass through, do not break */ default: setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT); enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, setPollSIMState, (void *) 1, NULL); return; } }
/** * Fetch information about UICC card type (SIM/USIM) * * \return UICC_Type: type of UICC card. */ static UICC_Type getUICCType(void) { ATResponse *atresponse = NULL; static UICC_Type UiccType = UICC_TYPE_UNKNOWN; int err; if (getRadioState() == RADIO_STATE_OFF || getRadioState() == RADIO_STATE_UNAVAILABLE) { return UICC_TYPE_UNKNOWN; } if (UiccType == UICC_TYPE_UNKNOWN) { err = at_send_command_singleline("AT+CUAD", "+CUAD:", &atresponse); if (err == AT_NOERROR) { /* USIM */ if(strstr(atresponse->p_intermediates->line, USIM_APPLICATION_ID)){ UiccType = UICC_TYPE_USIM; ALOGI("Detected card type USIM - stored"); } else { /* should maybe be unknown */ UiccType = UICC_TYPE_SIM; } } else if (at_get_error_type(err) != AT_ERROR) { /* Command failed - unknown card */ UiccType = UICC_TYPE_UNKNOWN; ALOGE("%s() Failed to detect card type - Retry at next request", __func__); } else { /* Legacy SIM */ /* TODO: CUAD only responds OK if SIM is inserted. * This is an inccorect AT response... */ UiccType = UICC_TYPE_SIM; ALOGI("Detected card type Legacy SIM - stored"); } at_response_free(atresponse); } return UiccType; }
static RIL_RadioState currentState(RILId rid, int *sim_status) { if (sim_status != NULL) { #ifdef MTK_GEMINI *sim_status = sim_inserted_status; #else *sim_status = 0; #endif } return getRadioState(rid); }
static int disconnect(void) { int e2napState, i, err; err = at_send_command("AT*ENAP=0"); if (err != AT_NOERROR && at_get_error_type(err) != CME_ERROR) return -1; for (i = 0; i < MBM_ENAP_DISCONNECT_TIME * 5; i++) { e2napState = getE2napState(); if ((e2napState == E2NAP_STATE_DISCONNECTED) || (e2napState == E2NAP_STATE_UNKNOWN) || (RADIO_STATE_UNAVAILABLE == getRadioState())) break; usleep(200 * 1000); } return 0; }
/** Returns one of SIM_*. Returns SIM_NOT_READY on error. */ static SIM_Status getSIMStatus(void) { ATResponse *atresponse = NULL; int err; SIM_Status ret = SIM_ABSENT; char *cpinLine; char *cpinResult; if (s_simRemoved) return SIM_ABSENT; if (getRadioState() == RADIO_STATE_OFF || getRadioState() == RADIO_STATE_UNAVAILABLE) { return SIM_NOT_READY; } err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &atresponse); if (err != AT_NOERROR) { if (at_get_error_type(err) == AT_ERROR) return SIM_NOT_READY; switch (at_get_cme_error(err)) { case CME_SIM_NOT_INSERTED: ret = SIM_ABSENT; break; case CME_SIM_PIN_REQUIRED: ret = SIM_PIN; break; case CME_SIM_PUK_REQUIRED: ret = SIM_PUK; break; case CME_SIM_PIN2_REQUIRED: ret = SIM_PIN2; break; case CME_SIM_PUK2_REQUIRED: ret = SIM_PUK2; break; case CME_NETWORK_PERSONALIZATION_PIN_REQUIRED: ret = SIM_NETWORK_PERSO; break; case CME_NETWORK_PERSONALIZATION_PUK_REQUIRED: ret = SIM_NETWORK_PERSO_PUK; break; case CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED: ret = SIM_NETWORK_SUBSET_PERSO; break; case CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED: ret = SIM_NETWORK_SUBSET_PERSO_PUK; break; case CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED: ret = SIM_SERVICE_PROVIDER_PERSO; break; case CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED: ret = SIM_SERVICE_PROVIDER_PERSO_PUK; break; case CME_PH_SIMLOCK_PIN_REQUIRED: /* PUK not in use by modem */ ret = SIM_SIM_PERSO; break; case CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED: ret = SIM_CORPORATE_PERSO; break; case CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED: ret = SIM_CORPORATE_PERSO_PUK; break; default: ret = SIM_NOT_READY; break; } return ret; } /* CPIN? has succeeded, now look at the result. */ cpinLine = atresponse->p_intermediates->line; err = at_tok_start(&cpinLine); if (err < 0) { ret = SIM_NOT_READY; goto done; } err = at_tok_nextstr(&cpinLine, &cpinResult); if (err < 0) { ret = SIM_NOT_READY; goto done; } if (0 == strcmp(cpinResult, "READY")) { ret = SIM_READY; } else if (0 == strcmp(cpinResult, "SIM PIN")) { ret = SIM_PIN; } else if (0 == strcmp(cpinResult, "SIM PUK")) { ret = SIM_PUK; } else if (0 == strcmp(cpinResult, "SIM PIN2")) { ret = SIM_PIN2; } else if (0 == strcmp(cpinResult, "SIM PUK2")) { ret = SIM_PUK2; } else if (0 == strcmp(cpinResult, "PH-NET PIN")) { ret = SIM_NETWORK_PERSO; } else if (0 == strcmp(cpinResult, "PH-NETSUB PIN")) { ret = SIM_NETWORK_SUBSET_PERSO; } else if (0 == strcmp(cpinResult, "PH-SP PIN")) { ret = SIM_SERVICE_PROVIDER_PERSO; } else if (0 == strcmp(cpinResult, "PH-CORP PIN")) { ret = SIM_CORPORATE_PERSO; } else if (0 == strcmp(cpinResult, "PH-SIMLOCK PIN")) { ret = SIM_SIM_PERSO; } else if (0 == strcmp(cpinResult, "PH-ESL PIN")) { ret = SIM_STERICSSON_LOCK; } else if (0 == strcmp(cpinResult, "BLOCKED")) { int numRetries = getNumRetries(RIL_REQUEST_ENTER_SIM_PUK); if (numRetries == -1 || numRetries == 0) ret = SIM_PERM_BLOCKED; else ret = SIM_PUK2_PERM_BLOCKED; } else if (0 == strcmp(cpinResult, "PH-SIM PIN")) { /* * Should not happen since lock must first be set from the phone. * Setting this lock is not supported by Android. */ ret = SIM_BLOCKED; } else { /* Unknown locks should not exist. Defaulting to "sim absent" */ ret = SIM_ABSENT; } done: at_response_free(atresponse); return ret; }
static RIL_RadioState currentState() { return getRadioState(); }
void requestSetupDefaultPDP(void *data, size_t datalen, RIL_Token t) { in_addr_t addr; in_addr_t gateway; const char *apn, *user, *pass, *auth; char *addresses = NULL; char *gateways = NULL; char *dnses = NULL; const char *type = NULL; RIL_Data_Call_Response_v6 response; int e2napState = getE2napState(); int err = -1; int cme_err, i, prof; (void) data; (void) datalen; prof = atoi(((const char **) data)[1]); apn = ((const char **) data)[2]; user = ((const char **) data)[3]; pass = ((const char **) data)[4]; auth = ((const char **) data)[5]; type = getNWType(((const char **) data)[6]); s_lastPdpFailCause = PDP_FAIL_ERROR_UNSPECIFIED; memset(&response, 0, sizeof(response)); response.ifname = ril_iface; response.cid = prof + 1; response.active = 0; response.type = (char *) type; response.suggestedRetryTime = -1; /* Handle case where Android framework tries to setup multiple PDPs when sending/receiving MMS. Tear down the default context if any attempt is made to setup a new context with different DataProfile. Requires changes to Android framework (RILConstants.java and GsmDataConnectionTracker.java). This need to be in place until the framework properly handles priorities on APNs */ if (e2napState > E2NAP_STATE_DISCONNECTED) { if (prof > RIL_DATA_PROFILE_DEFAULT) { ALOGD("%s() tearing down default cid:%d to allow cid:%d", __func__, s_ActiveCID, prof + 1); s_DeactCalled = 1; if (disconnect()) { goto down; } else { e2napState = getE2napState(); if (e2napState != E2NAP_STATE_DISCONNECTED) goto error; if (ifc_init()) goto error; if (ifc_down(ril_iface)) goto error; ifc_close(); requestOrSendPDPContextList(NULL); } } else { ALOGE("%s() denying data connection to APN '%s' Multiple PDP not supported!", __func__, apn); response.status = PDP_FAIL_INSUFFICIENT_RESOURCES; RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response)); return; } } down: e2napState = setE2napState(E2NAP_STATE_UNKNOWN); ALOGD("%s() requesting data connection to APN '%s'", __func__, apn); if (ifc_init()) { ALOGE("%s() Failed to set up ifc!", __func__); RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); return; } if (ifc_down(ril_iface)) { ALOGE("%s() Failed to bring down %s!", __func__, ril_iface); RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); return; } err = at_send_command("AT+CGDCONT=%d,\"IP\",\"%s\"", RIL_CID_IP, apn); if (err != AT_NOERROR) { cme_err = at_get_cme_error(err); ALOGE("%s() CGDCONT failed: %d, cme: %d", __func__, err, cme_err); RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); return; } if (networkAuth(auth, user, pass, RIL_CID_IP)) { RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); return; } /* Start data on PDP context for IP */ err = at_send_command("AT*ENAP=1,%d", RIL_CID_IP); if (err != AT_NOERROR) { cme_err = at_get_cme_error(err); ALOGE("requestSetupDefaultPDP: ENAP failed: %d cme: %d", err, cme_err); goto error; } for (i = 0; i < MBM_ENAP_CONNECT_TIME * 5; i++) { e2napState = getE2napState(); if (e2napState == E2NAP_STATE_CONNECTED || e2napState == E2NAP_STATE_DISCONNECTED || RADIO_STATE_UNAVAILABLE == getRadioState()) { ALOGD("%s() %s", __func__, e2napStateToString(e2napState)); break; } usleep(200 * 1000); } e2napState = getE2napState(); if (e2napState != E2NAP_STATE_CONNECTED) goto error; if (parse_ip_information(&addresses, &gateways, &dnses, &addr, &gateway) < 0) { ALOGE("%s() Failed to parse network interface data", __func__); goto error; } response.addresses = addresses; response.gateways = gateways; response.dnses = dnses; ALOGI("%s() Setting up interface %s,%s,%s", __func__, response.addresses, response.gateways, response.dnses); e2napState = getE2napState(); if (e2napState == E2NAP_STATE_DISCONNECTED) goto error; /* we got disconnected */ /* Don't use android netutils. We use our own and get the routing correct. * Carl Nordbeck */ if (ifc_configure(ril_iface, addr, gateway)) ALOGE("%s() Failed to configure the interface %s", __func__, ril_iface); ALOGI("IP Address %s, %s", addresses, e2napStateToString(e2napState)); e2napState = getE2napState(); if (e2napState == E2NAP_STATE_DISCONNECTED) goto error; /* we got disconnected */ response.active = 2; response.status = 0; s_ActiveCID = response.cid; RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response)); free(addresses); free(gateways); free(dnses); startPollFastDormancy(); return; error: mbm_check_error_cause(); response.status = s_lastPdpFailCause; /* Restore enap state and wait for enap to report disconnected*/ disconnect(); RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response)); free(addresses); free(gateways); free(dnses); }