aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYiming LI <yiming.xx.li@stericsson.com>2010-11-02 18:15:20 +0100
committerSverre Vegge <sverre.vegge@stericsson.com>2010-11-28 22:12:39 +0100
commitfb3650f35c4afebd95fd5a1142fdcc4670ab3560 (patch)
tree1a5e0e068a12b3c9527dcf63c9b9d18af09fd44b
parent3aaa5fb39e1040c7ce7a5a6bcec59e224def7827 (diff)
downloadu300-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.c3
-rw-r--r--atchannel.h14
-rw-r--r--misc.h2
-rw-r--r--u300-ril-network.c487
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. */
diff --git a/misc.h b/misc.h
index b5e0dcc..329c53d 100644
--- a/misc.h
+++ b/misc.h
@@ -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;