diff options
author | Yiming LI <yiming.xx.li@stericsson.com> | 2010-11-02 18:15:20 +0100 |
---|---|---|
committer | Sverre Vegge <sverre.vegge@stericsson.com> | 2010-11-28 22:12:39 +0100 |
commit | fb3650f35c4afebd95fd5a1142fdcc4670ab3560 (patch) | |
tree | 1a5e0e068a12b3c9527dcf63c9b9d18af09fd44b | |
parent | 3aaa5fb39e1040c7ce7a5a6bcec59e224def7827 (diff) | |
download | u300-fb3650f35c4afebd95fd5a1142fdcc4670ab3560.tar.gz |
Network: Implements failure reason for RIL_REQUEST_REGISTRATION_STATE.
Moves NUM_ELEMS from atchannel.c to misc.h.
Signed-off-by: Sverre Vegge <sverre.vegge@stericsson.com>
-rw-r--r-- | atchannel.c | 3 | ||||
-rw-r--r-- | atchannel.h | 14 | ||||
-rw-r--r-- | misc.h | 2 | ||||
-rw-r--r-- | u300-ril-network.c | 487 |
4 files changed, 359 insertions, 147 deletions
diff --git a/atchannel.c b/atchannel.c index 581b47d..97155c2 100644 --- a/atchannel.c +++ b/atchannel.c @@ -54,9 +54,6 @@ #define USE_NP 1 #endif /* HAVE_ANDROID_OS */ - -#define NUM_ELEMS(x) (sizeof(x) / sizeof(x[0])) - #define MAX_AT_RESPONSE (8 * 1024) #define HANDSHAKE_RETRY_COUNT 8 #define HANDSHAKE_TIMEOUT_MSEC 250 diff --git a/atchannel.h b/atchannel.h index 8d502f0..7c4dcd9 100644 --- a/atchannel.h +++ b/atchannel.h @@ -180,6 +180,20 @@ typedef enum { } ATCmsError; typedef enum { + GENERAL = 0, + AUTHENTICATION_FAILURE = 1, + IMSI_UNKNOWN_IN_HLR = 2, + ILLEGAL_MS = 3, + ILLEGAL_ME = 4, + PLMN_NOT_ALLOWED = 5, + LOCATION_AREA_NOT_ALLOWED = 6, + ROAMING_NOT_ALLOWED = 7, + NO_SUITABLE_CELL_IN_LOCATION_AREA = 8, + NETWORK_FAILURE = 9, + PERSISTEN_LOCATION_UPDATE_REJECT = 10 +} Reg_Deny_DetailReason; + +typedef enum { NO_RESULT, /* No intermediate response expected. */ NUMERIC, /* A single intermediate response starting with a 0-9. */ SINGLELINE, /* A single intermediate response starting with a prefix. */ @@ -58,6 +58,8 @@ int parseTlv(/*in*/ const char *stream, #define TLV_DATA(tlv, pos) (((unsigned)char2nib(tlv.data[(pos) * 2 + 0]) << 4) | \ ((unsigned)char2nib(tlv.data[(pos) * 2 + 1]) << 0)) +#define NUM_ELEMS(x) (sizeof(x) / sizeof(x[0])) + #ifdef __cplusplus } #endif diff --git a/u300-ril-network.c b/u300-ril-network.c index aad4730..a8b2c58 100644 --- a/u300-ril-network.c +++ b/u300-ril-network.c @@ -1152,6 +1152,50 @@ error: } /** + * Convert detailedReason from modem to what Android expects. + * Called in requestRegistrationState(). + */ +static Reg_Deny_DetailReason ConvertRegistrationDenyReason(int detailedReason) +{ + Reg_Deny_DetailReason reason; + + switch (detailedReason) { + case 2: + reason = IMSI_UNKNOWN_IN_HLR; + break; + case 3: + reason = ILLEGAL_MS; + break; + case 6: + reason = ILLEGAL_ME; + break; + case 11: + reason = PLMN_NOT_ALLOWED; + break; + case 12: + reason = LOCATION_AREA_NOT_ALLOWED; + break; + case 13: + reason = ROAMING_NOT_ALLOWED; + break; + case 15: + reason = NO_SUITABLE_CELL_IN_LOCATION_AREA; + break; + case 17: + reason = NETWORK_FAILURE; + break; + case 257: + reason = AUTHENTICATION_FAILURE; + break; + default: + reason = GENERAL; + break; + } + + return reason; +} + +/** * RIL_REQUEST_REGISTRATION_STATE * * Request current registration state. @@ -1159,36 +1203,45 @@ error: void requestRegistrationState(void *data, size_t datalen, RIL_Token t) { int err = 0; - int response[4]; + int response[14]; char *responseStr[14]; ATResponse *atresponse = NULL; char *line; int commas = 0; int skip, tmp; int count = 3; + int detailedReason; + unsigned int i; + int getAcT = 0; /* set to 1 to send CGREG to retrieve AcT. */ /* * IMPORTANT: Will take screen state lock here. Make sure to always call * releaseScreenStateLock BEFORE returning! */ getScreenStateLock(); + if (0 == getScreenState()) at_send_command("AT+CGREG=2;*EREG=2", NULL); /* Ignore the response, not vital. */ /* Setting default values in case values are not returned by AT command */ - memset(responseStr, 0, sizeof(responseStr)); + for (i = 0; i < NUM_ELEMS(responseStr); i++) { + responseStr[i] = NULL; + } + memset(response, 0, sizeof(response)); response[1] = -1; response[2] = -1; err = at_send_command_singleline("AT*EREG?", "*EREG:", &atresponse); + if (err < 0 || atresponse->success == 0 || - atresponse->p_intermediates == NULL) + atresponse->p_intermediates == NULL) goto error; line = atresponse->p_intermediates->line; err = at_tok_start(&line); + if (err < 0) goto error; @@ -1210,69 +1263,177 @@ void requestRegistrationState(void *data, size_t datalen, RIL_Token t) /* Count number of commas */ err = at_tok_charcounter(line, ',', &commas); + if (err < 0) goto error; switch (commas) { case 0: /* *EREG: <stat> */ err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; + + if (err < 0) + goto error; + break; case 1: /* *EREG: <n>, <stat> */ err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; + + if (err < 0) + goto error; + break; case 2: /* *EREG: <stat>, <lac>, <cid> */ err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nexthexint(&line, &response[1]); - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nexthexint(&line, &response[2]); - if (err < 0) goto error; + + if (err < 0) + goto error; + break; - case 3: /* *EREG: <n>, <stat>, <lac>, <cid> */ - /* *EREG: <stat>, <lac>, <cid>, <AcT> */ + case 3: err = at_tok_nextint(&line, &tmp); + if (err < 0) goto error; + /* We need to check if the second parameter is <lac> */ - if (*(line) == '"') { + if (*(line) == '"') { /* *EREG: <stat>, <lac>, <cid>, <AcT> */ response[0] = tmp; /* <stat> */ err = at_tok_nexthexint(&line, &response[1]); /* <lac> */ - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nexthexint(&line, &response[2]); /* <cid> */ - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nextint(&line, &response[3]); /* <AcT> */ - if (err < 0) goto error; + + if (err < 0) + goto error; + count = 4; - } else { + getAcT = 1; + } else { /* *EREG: <n>, <stat>, <lac>, <cid> */ err = at_tok_nextint(&line, &response[0]); /* <stat> */ - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nexthexint(&line, &response[1]); /* <lac> */ - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nexthexint(&line, &response[2]); /* <cid> */ - if (err < 0) goto error; + + if (err < 0) + goto error; } + break; - case 4: /* *EREG: <n>, <stat>, <lac>, <cid>, <AcT> */ + case 4: + err = at_tok_nextint(&line, &tmp); /* <n> */ + + if (err < 0) + goto error; + + if (*(line) == '"' || *(line) == ',') { /* *EREG: <stat>, <lac>, <cid>, <AcT>, <detailedReason> */ + response[0] = tmp; /* <stat> */ + + if (tmp == 3) { /* skip lac, cid and AcT if <stat> is 3, i.e. registration denied. */ + + at_tok_nexthexint(&line, &skip); /* <lac> */ + at_tok_nexthexint(&line, &skip); /* <cid> */ + at_tok_nextint(&line, &skip); /* <AcT> */ + err = at_tok_nextint(&line, &detailedReason); /*<detailedReason>*/ + + if (err < 0) + goto error; + + response[3] = 0; /* In case of registration denied, set AcT to 0, i.e unknown */ + count = 14; + + } else { + /* modem might return detailedReason if <stat> is 0, 2, 3, 4. not returning AcT. */ + count = 3; + } + } else { /* *EREG: <n>, <stat>, <lac>, <cid>, <AcT> */ + err = at_tok_nextint(&line, &response[0]); /* <stat> */ + + if (err < 0) + goto error; + + err = at_tok_nexthexint(&line, &response[1]); /* <lac> */ + + if (err < 0) + goto error; + + err = at_tok_nexthexint(&line, &response[2]); /* <cid> */ + + if (err < 0) + goto error; + + err = at_tok_nextint(&line, &response[3]); /* <AcT> */ + + if (err < 0) + goto error; + + count = 4; + getAcT = 1; + } + + break; + case 5: /* *EREG: <n>, <stat>, <lac>, <cid>, <AcT>, <detailedReason> */ err = at_tok_nextint(&line, &skip); /* <n> */ - if (err < 0) goto error; + + if (err < 0) + goto error; + err = at_tok_nextint(&line, &response[0]); /* <stat> */ - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[1]); /* <lac> */ - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[2]); /* <cid> */ - if (err < 0) goto error; - err = at_tok_nextint(&line, &response[3]); /* <AcT> */ - if (err < 0) goto error; - count = 4; - break; + if (err < 0) + goto error; + + if (response[0] == 3) { /* skip lac, cid and AcT if registration denied. */ + + at_tok_nexthexint(&line, &skip); /* <lac> */ + at_tok_nexthexint(&line, &skip); /* <cid> */ + at_tok_nextint(&line, &skip); /* <AcT> */ + err = at_tok_nextint(&line, &detailedReason); /*<detailedReason>*/ + + if (err < 0) + goto error; + + response[3] = 0; /* In case of registration denied, set AcT to 0, i.e Unknown */ + count = 14; + + } else { + /* modem might return detailedReason if <stat> is 0, 2, 3, 4. + we should not return AcT. */ + count = 3; + } + + break; default: LOGE("Invalid input.\r\n"); goto error; @@ -1281,128 +1442,169 @@ void requestRegistrationState(void *data, size_t datalen, RIL_Token t) /* Converting to stringlist for Android */ asprintf(&responseStr[0], "%d", response[0]); /* state */ - if (response[1] >= 0) - asprintf(&responseStr[1], "%04x", response[1]); /* LAC */ - else - responseStr[1] = NULL; + if (count == 14) { - if (response[2] >= 0) - asprintf(&responseStr[2], "%08x", response[2]); /* CID */ - else - responseStr[2] = NULL; + response[13] = ConvertRegistrationDenyReason(detailedReason); + asprintf(&responseStr[3], "%d", response[3]); /* AcT */ + asprintf(&responseStr[13], "%d", response[13]); /* detailedReason */ - if (count > 3) { - /* - * Android expects this for response[3]: - * - * 0 - Unknown, 1 - GPRS, 2 - EDGE, 3 - UMTS, - * 4 - IS95A, 5 - IS95B, 6 - 1xRTT, - * 7 - EvDo Rev. 0, 8 - EvDo Rev. A, - * 9 - HSDPA, 10 - HSUPA, 11 - HSPA - * - * *EREG response: - * 0 GSM - * 1 GSM Compact Not Supported - * 2 UTRAN - * - * +CGREG response: - * 0 GSM - * 1 GSM Compact Not Supported - * 2 UTRAN - * 3 GSM w/EGPRS - * 4 UTRAN w/HSDPA - * 5 UTRAN w/HSUPA - * 6 UTRAN w/HSUPA and HSDPA - * - * Workaround: Use +CGREG AcT to comply with Android NetworkType - */ - int networkType; -/****** WORKAROUND START ******/ - int cgregAcT; - int actSet = 0; - ATResponse *atresponse2 = NULL; + } else { - LOGI("Trying to replace network type with CGREG result..."); + if (response[1] >= 0) + asprintf(&responseStr[1], "%04x", response[1]); /* LAC */ + else + responseStr[1] = NULL; + + if (response[2] >= 0) + asprintf(&responseStr[2], "%08x", response[2]); /* CID */ + else + responseStr[2] = NULL; + + if (getAcT) { + /* + * Android expects this for response[3]: + * + * 0 - Unknown, 1 - GPRS, 2 - EDGE, 3 - UMTS, + * 4 - IS95A, 5 - IS95B, 6 - 1xRTT, + * 7 - EvDo Rev. 0, 8 - EvDo Rev. A, + * 9 - HSDPA, 10 - HSUPA, 11 - HSPA + * + * *EREG response: + * 0 GSM + * 1 GSM Compact Not Supported + * 2 UTRAN + * + * +CGREG response: + * 0 GSM + * 1 GSM Compact Not Supported + * 2 UTRAN + * 3 GSM w/EGPRS + * 4 UTRAN w/HSDPA + * 5 UTRAN w/HSUPA + * 6 UTRAN w/HSUPA and HSDPA + * + * Workaround: Use +CGREG AcT to comply with Android NetworkType + */ + int networkType; + /****** WORKAROUND START ******/ + int cgregAcT; + int actSet = 0; + ATResponse *atresponse2 = NULL; + + LOGI("Trying to replace network type with CGREG result..."); + + err = at_send_command_singleline("AT+CGREG?", "+CGREG:", &atresponse2); + + if (err < 0 || + atresponse2->success == 0 || atresponse2->p_intermediates == NULL) + goto wa_final; + + line = atresponse2->p_intermediates->line; + err = at_tok_start(&line); - err = at_send_command_singleline("AT+CGREG?", "+CGREG:", &atresponse2); - if (err < 0 || - atresponse2->success == 0 || atresponse2->p_intermediates == NULL) - goto wa_final; + if (err < 0) + goto wa_final; - line = atresponse2->p_intermediates->line; - err = at_tok_start(&line); - if (err < 0) goto wa_final; + /* Count number of commas */ + commas = 0; + err = at_tok_charcounter(line, ',', &commas); - /* Count number of commas */ - commas = 0; - err = at_tok_charcounter(line, ',', &commas); - if (err < 0) goto error; + if (err < 0) + goto error; + + if (commas == 3) { /* +CGREG: <n>, <stat>, <lac>, <cid> */ + /* +CGREG: <stat>, <lac>, <cid>, <AcT> */ + err = at_tok_nextint(&line, &tmp); + + if (err < 0) + goto wa_final; + + /* We need to check if the second parameter is <lac> */ + if (*(line) == '"') { + err = at_tok_nexthexint(&line, &skip); /* <lac> */ + + if (err < 0) + goto wa_final; + + err = at_tok_nexthexint(&line, &skip); /* <cid> */ - if (commas == 3) { /* +CGREG: <n>, <stat>, <lac>, <cid> */ - /* +CGREG: <stat>, <lac>, <cid>, <AcT> */ - err = at_tok_nextint(&line, &tmp); - if (err < 0) goto wa_final; + if (err < 0) + goto wa_final; + + err = at_tok_nextint(&line, &cgregAcT); /* <AcT> */ + + if (err < 0) + goto wa_final; + + actSet = 1; + } + } else if (commas == 4) { /* +CGREG: <n>, <stat>, <lac>, <cid>, <AcT> */ + err = at_tok_nextint(&line, &skip); /* <n> */ + + if (err < 0) + goto wa_final; + + err = at_tok_nextint(&line, &skip); /* <stat> */ + + if (err < 0) + goto wa_final; - /* We need to check if the second parameter is <lac> */ - if (*(line) == '"') { err = at_tok_nexthexint(&line, &skip); /* <lac> */ - if (err < 0) goto wa_final; + + if (err < 0) + goto wa_final; + err = at_tok_nexthexint(&line, &skip); /* <cid> */ - if (err < 0) goto wa_final; + + if (err < 0) + goto wa_final; + err = at_tok_nextint(&line, &cgregAcT); /* <AcT> */ - if (err < 0) goto wa_final; + + if (err < 0) + goto wa_final; + actSet = 1; } - } - else if (commas == 4) { /* +CGREG: <n>, <stat>, <lac>, <cid>, <AcT> */ - err = at_tok_nextint(&line, &skip); /* <n> */ - if (err < 0) goto wa_final; - err = at_tok_nextint(&line, &skip); /* <stat> */ - if (err < 0) goto wa_final; - err = at_tok_nexthexint(&line, &skip); /* <lac> */ - if (err < 0) goto wa_final; - err = at_tok_nexthexint(&line, &skip); /* <cid> */ - if (err < 0) goto wa_final; - err = at_tok_nextint(&line, &cgregAcT); /* <AcT> */ - if (err < 0) goto wa_final; - actSet = 1; - } wa_final: - if (actSet) { - LOGI("AcT switched from %d to %d", response[3], cgregAcT); - response[3] = cgregAcT; - } - at_response_free(atresponse2); -/****** WORKAROUND END ******/ - /* Conversion between AT AcT and Android NetworkType */ - switch (response[3]) { - case CGREG_ACT_GSM: - networkType = 1; - break; - case CGREG_ACT_UTRAN: - networkType = 3; - break; - case CGREG_ACT_GSM_EGPRS: - networkType = 2; - break; - case CGREG_ACT_UTRAN_HSDPA: - networkType = 9; - break; - case CGREG_ACT_UTRAN_HSUPA: - networkType = 10; - break; - case CGREG_ACT_UTRAN_HSUPA_HSDPA: - networkType = 11; - break; - default: - networkType = 0; - break; + if (actSet) { + LOGI("AcT switched from %d to %d", response[3], cgregAcT); + response[3] = cgregAcT; + } + + at_response_free(atresponse2); + /****** WORKAROUND END ******/ + + /* Conversion between AT AcT and Android NetworkType */ + switch (response[3]) { + case CGREG_ACT_GSM: + networkType = 1; + break; + case CGREG_ACT_UTRAN: + networkType = 3; + break; + case CGREG_ACT_GSM_EGPRS: + networkType = 2; + break; + case CGREG_ACT_UTRAN_HSDPA: + networkType = 9; + break; + case CGREG_ACT_UTRAN_HSUPA: + networkType = 10; + break; + case CGREG_ACT_UTRAN_HSUPA_HSDPA: + networkType = 11; + break; + default: + networkType = 0; + break; + } + + asprintf(&responseStr[3], "%d", networkType); /* available radio technology */ } - asprintf(&responseStr[3], "%d", networkType); /* available radio technology */ } - /* * Note that Ril.h specifies that all 14 bytes of the response is * mandatory. However the Android reference RIL cuts the length of the @@ -1410,22 +1612,19 @@ wa_final: * We are currently following the same way and not returning more than the * responses that we have available information for. See "count" below. */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, - count * sizeof(char *)); + RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count * sizeof(char *)); finally: + if (!getScreenState()) at_send_command("AT+CGREG=0;*EREG=0", NULL); + releaseScreenStateLock(); /* Important! */ - if (responseStr[0]) - free(responseStr[0]); - if (responseStr[1]) - free(responseStr[1]); - if (responseStr[2]) - free(responseStr[2]); - if (responseStr[3]) - free(responseStr[3]); + for (i = 0; i < NUM_ELEMS(responseStr); i++) { + if (responseStr[i]) + free(responseStr[i]); + } at_response_free(atresponse); return; |