#include <hayes-ril.h>
+/*
+ * Signal Strength
+ */
+
void at2ril_signal_strength(RIL_SignalStrength *ss, int *values)
{
const int dbm_table[8] = {135,125,115,105,95,85,75,70};
return AT_RESPONSE_HANDLED_OK;
error_data:
- LOGE("No valid data fiven to AT+CSQ response!");
+ LOGE("No valid data given to AT+CSQ response!");
+
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
at_response_data_free(response_data, response_data_count);
return AT_RESPONSE_HANDLED_ERROR;
{
at_send_expect_to_func("AT+CSQ", NULL, NULL, t, at_csq_expect);
}
+
+/*
+ * Network registration
+ */
+
+int at_creg_handle(char **registration_state, struct at_response_data **response_data, int response_data_count)
+{
+ int state = 0;
+ char *lac = NULL;
+ char *cid = NULL;
+
+ if(registration_state == NULL || response_data == NULL || response_data_count <= 0)
+ return -1;
+
+ /*
+ * Ok you have to be careful here
+ * The solicited version of the CREG response is
+ * +CREG: n, stat, [lac, cid]
+ * and the unsolicited version is
+ * +CREG: stat, [lac, cid]
+ * The <n> parameter is basically "is unsolicited creg on?"
+ * which it should always be
+ *
+ * Also since the LAC and CID are only reported when registered,
+ * we can have 1, 2, 3, or 4 arguments here
+ *
+ * finally, a +CGREG: answer may have a fifth value that corresponds
+ * to the network type, as in;
+ *
+ * +CGREG: n, stat [,lac, cid [,networkType]]
+ */
+
+ // Only handle CREG responses
+ switch(response_data_count) {
+ case 1: // UNSOL response, unregistered
+ if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
+ return -1;
+ state = response_data[0]->value.n;
+
+ break;
+ case 2: // SOL response, unregistered
+ // Skip first argument
+ if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
+ return -1;
+ state = response_data[1]->value.n;
+
+ break;
+ case 3: // UNSOL response, registered
+ if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
+ return -1;
+ state = response_data[0]->value.n;
+
+ if(response_data[1]->type != AT_RESPONSE_DATA_STRING)
+ return -1;
+ lac = response_data[1]->value.s;
+
+ if(response_data[2]->type != AT_RESPONSE_DATA_STRING)
+ return -1;
+ cid = response_data[2]->value.s;
+
+ break;
+ case 4: // SOL response, registered
+ if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
+ return -1;
+ state = response_data[1]->value.n;
+
+ if(response_data[2]->type != AT_RESPONSE_DATA_STRING)
+ return -1;
+ lac = response_data[2]->value.s;
+
+ if(response_data[3]->type != AT_RESPONSE_DATA_STRING)
+ return -1;
+ cid = response_data[3]->value.s;
+
+ break;
+ default:
+ return -1;
+ }
+
+ asprintf(&(registration_state[0]), "%d", state);
+ registration_state[1] = strdup(lac);
+ registration_state[2] = strdup(cid);
+
+ return 0;
+}
+
+void ril_registration_state_free(char **registration_state)
+{
+ int i;
+
+ for(i=0 ; i < 14 ; i++) {
+ if(registration_state[i] != NULL)
+ free(registration_state[i]);
+ }
+
+
+ free(registration_state);
+}
+
+int at_creg_expect(struct at_response *response, void *data, RIL_Token t)
+{
+ struct at_response_data **response_data = NULL;
+ int response_data_count = 0;
+
+ char **registration_state = NULL;
+ int rc;
+
+ if(response->status == AT_STATUS_UNDEF)
+ return AT_RESPONSE_UNHANDELD_REASON_STATUS;
+
+ if(response->data == NULL || response->data_count <= 0) {
+ LOGE("No data given to AT+CREG response!");
+ return AT_RESPONSE_HANDLED_ERROR;
+ }
+
+ LOGE("Caught valid AT+CREG response!");
+
+ response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
+ if(response_data_count <= 0)
+ goto error_data;
+
+ registration_state = calloc(1, sizeof(char *) * 15);
+ rc = at_creg_handle(registration_state, response_data, response_data_count);
+ if(rc < 0) {
+ ril_registration_state_free(registration_state);
+ goto error_data;
+ }
+
+ RIL_onRequestComplete(t, RIL_E_SUCCESS, registration_state, sizeof(char *) * 15);
+
+ ril_registration_state_free(registration_state);
+ at_response_data_free(response_data, response_data_count);
+
+ return AT_RESPONSE_HANDLED_OK;
+
+error_data:
+ LOGE("No valid data given to AT+CREG response!");
+
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ at_response_data_free(response_data, response_data_count);
+
+ return AT_RESPONSE_HANDLED_ERROR;
+}
+
+void at_creg_unexpect(struct at_response *response)
+{
+ struct at_response_data **response_data = NULL;
+ int response_data_count = 0;
+
+ char **registration_state = NULL;
+ int rc;
+
+ if(response->data == NULL || response->data_count <= 0) {
+ LOGE("No data given to AT+CREG unsol!");
+ return;
+ }
+
+ LOGE("Caught valid AT+CREG unsol!");
+
+ response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
+ if(response_data_count <= 0)
+ goto error_data;
+
+ registration_state = calloc(1, sizeof(char *) * 15);
+ rc = at_creg_handle(registration_state, response_data, response_data_count);
+ if(rc < 0) {
+ ril_registration_state_free(registration_state);
+ goto error_data;
+ }
+
+ if(ril_globals.registration_state != NULL)
+ ril_registration_state_free(ril_globals.registration_state);
+
+ ril_globals.registration_state = registration_state;
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
+
+error_data:
+ LOGE("No valid data given to AT+CREG unsol!");
+
+ at_response_data_free(response_data, response_data_count);
+}
+
+void ril_request_registration_state(RIL_Token t, void *data, size_t length)
+{
+ if(ril_globals.registration_state != NULL) {
+ // There is UNSOL data there
+ RIL_onRequestComplete(t, RIL_E_SUCCESS, ril_globals.registration_state, sizeof(char *) * 15);
+
+ ril_registration_state_free(ril_globals.registration_state);
+ ril_globals.registration_state = NULL;
+ } else {
+ at_send_expect_to_func("AT+CREG?", NULL, NULL, t, at_creg_expect);
+ }
+}