summaryrefslogtreecommitdiffstats
path: root/network.c
diff options
context:
space:
mode:
authorWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-09-06 00:19:36 +0200
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-09-06 00:19:36 +0200
commitf35a9bbd1ebb52433f313c675fbe01bb1ca96d7d (patch)
treec1aff224fd4a2ea2e5e06805c7caff5406b0ab42 /network.c
parent06cf4fe68ad096961b4b9c653ba2bc31d270f009 (diff)
downloadqmi-ril-f35a9bbd1ebb52433f313c675fbe01bb1ca96d7d.tar.gz
qmi-ril-f35a9bbd1ebb52433f313c675fbe01bb1ca96d7d.tar.bz2
qmi-ril-f35a9bbd1ebb52433f313c675fbe01bb1ca96d7d.zip
initial version of QMI-RILHEADmaster
The RIL uses libqmi. qmicli and ModemManager were used as references for using libqmi. The request processing is modelled after Samsung-RIL and a lot of code could be reused for QMI-RIL. Establishing a data connection succeeds and mobile data is working in early testing. However, there is not yet a routine for handling interruptions and notifying Android about them. Information about the serving network including signal strength are retrieved and an unlocked SIM card is recognized. Reading data from the SIM and requesting the usual device information should work as well. Support for voice calls and SMS is completely missing at this point. Signed-off-by: Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
Diffstat (limited to 'network.c')
-rw-r--r--network.c664
1 files changed, 664 insertions, 0 deletions
diff --git a/network.c b/network.c
new file mode 100644
index 0000000..e0488c0
--- /dev/null
+++ b/network.c
@@ -0,0 +1,664 @@
+/*
+ * This file is part of QMI-RIL.
+ *
+ * Copyright (C) 2017 Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
+ *
+ * QMI-RIL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * QMI-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with QMI-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <qmi-ril.h>
+#include <plmn_list.h>
+
+void serving_system_indication_cb(QmiClientNas *client,
+ QmiIndicationNasServingSystemOutput *output)
+{
+ RIL_LOGD("Got serving system indication");
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
+ NULL, 0);
+}
+
+int qmi2ril_signal_strength(gint8 qmi_strength)
+{
+ int ril_strength;
+
+ ril_strength = (int) qmi_strength / 2 + 56;
+
+ if (ril_strength < 0)
+ ril_strength = 0;
+ else if (ril_strength > 31)
+ ril_strength = 31;
+
+ return ril_strength;
+}
+
+void nas_event_report_indication_cb(QmiClientNas *client,
+ QmiIndicationNasEventReportOutput *output)
+{
+ RIL_SignalStrength_v6 ril_strength;
+ gint8 qmi_strength, rsrq;
+ gint16 rsrp, snr;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return;
+
+ qmi_indication_nas_event_report_output_get_signal_strength(
+ output, &qmi_strength, NULL, NULL);
+
+ RIL_LOGD("Successfully got signal strength through indication\n"
+ "Current: '%d dBm'", qmi_strength);
+
+ /* RSRQ */
+ if (qmi_indication_nas_event_report_output_get_rsrq(
+ output, &rsrq, NULL, NULL)) {
+ RIL_LOGD("RSRQ: '%d dB'", rsrq);
+ } else
+ return;
+
+ /* LTE SNR */
+ if (qmi_indication_nas_event_report_output_get_lte_snr(
+ output, &snr, NULL)) {
+ RIL_LOGD("SNR: '%.1lf dB'", (0.1) * ((gdouble)snr));
+ } else
+ return;
+
+ /* LTE RSRP */
+ if (qmi_indication_nas_event_report_output_get_lte_rsrp(
+ output, &rsrp, NULL)) {
+ RIL_LOGD("RSRP: '%d dBm'", rsrp);
+ } else
+ return;
+
+ memset(&ril_strength, -1, sizeof(RIL_SignalStrength_v6));
+ ril_strength.LTE_SignalStrength.signalStrength = qmi2ril_signal_strength(qmi_strength);
+ ril_strength.LTE_SignalStrength.rsrp = -rsrp;
+ ril_strength.LTE_SignalStrength.rsrq = -rsrq;
+ ril_strength.LTE_SignalStrength.rssnr = snr;
+ ril_strength.LTE_SignalStrength.cqi = INT_MAX;
+
+ ril_request_unsolicited(RIL_UNSOL_SIGNAL_STRENGTH,
+ (void *) &ril_strength,
+ sizeof(ril_strength));
+
+ RIL_LOGD("reported signal strength");
+}
+
+static void get_signal_strength_ready(QmiClientNas *client,
+ GAsyncResult *res,
+ RIL_Token token)
+{
+ RIL_SignalStrength_v6 ril_strength;
+ QmiMessageNasGetSignalStrengthOutput *output;
+ GError *error = NULL;
+ gint8 qmi_strength, rsrq;
+ gint16 rsrp, snr;
+ int rc;
+
+ output = qmi_client_nas_get_signal_strength_finish(client, res, &error);
+ if (!output) {
+ RIL_LOGE("%s: error: operation failed: %s", __func__,
+ error->message);
+ goto error;
+ }
+
+ if (!qmi_message_nas_get_signal_strength_output_get_result(output, &error)) {
+ RIL_LOGE("%s: error: couldn't get signal strength: %s",
+ __func__, error->message);
+ goto error;
+ }
+
+ qmi_message_nas_get_signal_strength_output_get_signal_strength(
+ output, &qmi_strength, NULL, NULL);
+
+ RIL_LOGD("Successfully got signal strength\n"
+ "Current: '%d dBm'", qmi_strength);
+
+ /* RSRQ */
+ if (qmi_message_nas_get_signal_strength_output_get_rsrq(
+ output, &rsrq, NULL, NULL)) {
+ RIL_LOGD("RSRQ: '%d dB'", rsrq);
+ } else
+ goto error;
+
+ /* LTE SNR */
+ if (qmi_message_nas_get_signal_strength_output_get_lte_snr(
+ output, &snr, NULL)) {
+ RIL_LOGD("SNR: '%.1lf dB'", (0.1) * ((gdouble)snr));
+ } else
+ goto error;
+
+ /* LTE RSRP */
+ if (qmi_message_nas_get_signal_strength_output_get_lte_rsrp(
+ output, &rsrp, NULL)) {
+ RIL_LOGD("RSRP: '%d dBm'", rsrp);
+ } else
+ goto error;
+
+ memset(&ril_strength, -1, sizeof(RIL_SignalStrength_v6));
+ ril_strength.LTE_SignalStrength.signalStrength = qmi2ril_signal_strength(qmi_strength);
+ ril_strength.LTE_SignalStrength.rsrp = -rsrp;
+ ril_strength.LTE_SignalStrength.rsrq = -rsrq;
+ ril_strength.LTE_SignalStrength.rssnr = snr;
+ ril_strength.LTE_SignalStrength.cqi = INT_MAX;
+
+ ril_request_complete(token, RIL_E_SUCCESS, (void *) &ril_strength, sizeof(ril_strength));
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ if (error)
+ g_error_free(error);
+ if (output)
+ qmi_message_nas_get_signal_strength_output_unref(output);
+}
+
+static QmiMessageNasGetSignalStrengthInput
+*ril2qmi_signal_strength_input_create(void)
+{
+ GError *error = NULL;
+ QmiMessageNasGetSignalStrengthInput *input;
+ QmiNasSignalStrengthRequest mask;
+
+ mask = (QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSRQ |
+ QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_SNR |
+ QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_RSRP);
+
+ input = qmi_message_nas_get_signal_strength_input_new();
+ if (!qmi_message_nas_get_signal_strength_input_set_request_mask(
+ input,
+ mask,
+ &error)) {
+ RIL_LOGE("error: couldn't create input data bundle: '%s'",
+ error->message);
+ g_error_free(error);
+ qmi_message_nas_get_signal_strength_input_unref(input);
+ input = NULL;
+ }
+
+ return input;
+}
+
+int ril_request_signal_strength(void *data, size_t size, RIL_Token token)
+{
+ QmiMessageNasGetSignalStrengthInput *input;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ input = ril2qmi_signal_strength_input_create();
+
+ qmi_client_nas_get_signal_strength(ctx->NasClient, input, 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)get_signal_strength_ready,
+ token);
+
+ qmi_message_nas_get_signal_strength_input_unref(input);
+
+ return RIL_REQUEST_HANDLED;
+}
+
+static void
+get_system_selection_preference_ready(QmiClientNas *client,
+ GAsyncResult *res,
+ RIL_Token token)
+{
+ QmiMessageNasGetSystemSelectionPreferenceOutput *output;
+ GError *error = NULL;
+ QmiNasNetworkSelectionPreference qmi_network_selection;
+ int ril_network_selection;
+
+ output = qmi_client_nas_get_system_selection_preference_finish(
+ client, res, &error);
+ if (!output) {
+ RIL_LOGE("%s: error: operation failed: %s", __func__,
+ error->message);
+ goto error;
+ }
+
+ if (!qmi_message_nas_get_system_selection_preference_output_get_result(output, &error)) {
+ RIL_LOGE("error: couldn't get system_selection preference: %s", error->message);
+ goto error;
+ }
+
+ RIL_LOGD("Successfully got system selection preference");
+
+ if (qmi_message_nas_get_system_selection_preference_output_get_network_selection_preference(
+ output, &qmi_network_selection, NULL)) {
+ RIL_LOGD("Network selection preference: '%s'",
+ qmi_nas_network_selection_preference_get_string(qmi_network_selection));
+
+ switch (qmi_network_selection) {
+ case QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC:
+ ril_network_selection = 0;
+ case QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL:
+ ril_network_selection = 1;
+ }
+ } else
+ goto error;
+
+ ril_request_complete(token, RIL_E_SUCCESS,
+ (void *) &ril_network_selection,
+ sizeof(ril_network_selection));
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ if (error)
+ g_error_free(error);
+ if (output)
+ qmi_message_nas_get_system_selection_preference_output_unref(output);
+}
+
+int ril_request_query_network_selection_mode(void *data, size_t size,
+ RIL_Token token)
+{
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ qmi_client_nas_get_system_selection_preference(ctx->NasClient,
+ NULL, 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)get_system_selection_preference_ready,
+ token);
+
+ return RIL_REQUEST_HANDLED;
+}
+
+int ril_request_set_preferred_network_type(void *data, size_t size,
+ RIL_Token token)
+{
+ int type;
+ int rc;
+
+ if (data == NULL || size < sizeof(int))
+ goto error;
+
+ type = *((int *) data);
+
+ RIL_LOGD("request for setting %d as preferred network type", type);
+ RIL_LOGE("%s: TODO: implement me!", __func__);
+
+ ril_request_complete(token, RIL_E_SUCCESS, NULL, 0);
+ rc = RIL_REQUEST_COMPLETED;
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int qmi2ril_net_operator(QmiMessageNasGetOperatorNameOutputOperatorPlmnListElement *element,
+ char **operator_long, char **operator_short,
+ char **plmn)
+{
+ char buffer[7] = { 0 };
+ unsigned int mcc = 0;
+ unsigned int mnc = 0;
+ unsigned int i;
+ int rc;
+
+ *plmn = NULL;
+
+ strncpy(buffer, element->mcc, 3);
+ strncpy(&buffer[3], element->mnc, 3);
+ for (i = 0; i < 7; i++) {
+ if (!isdigit(buffer[i])) {
+ buffer[i] = '\0';
+ break;
+ }
+ }
+
+ if (buffer[0] == '\0')
+ goto error;
+
+ *plmn = strdup(buffer);
+
+ *operator_long = NULL;
+ *operator_short = NULL;
+
+ if (buffer[5] == '\0')
+ rc = sscanf((char *) &buffer, "%3u%2u", &mcc, &mnc);
+ else
+ rc = sscanf((char *) &buffer, "%3u%3u", &mcc, &mnc);
+ if (rc < 2)
+ goto error;
+
+ for (i = 0 ; i < plmn_list_count ; i++) {
+ if (plmn_list[i].mcc == mcc
+ && plmn_list[i].mnc == mnc) {
+ *operator_long = strdup(plmn_list[i].operator_long);
+ *operator_short = strdup(plmn_list[i].operator_short);
+ }
+ }
+
+ if (*operator_long == NULL || *operator_short == NULL) {
+ RIL_LOGE("%s: Finding operator with PLMN %d%d failed", __func__, mcc, mnc);
+ goto error;
+ } else
+ RIL_LOGD("%s: Found operator with PLMN %d%d", __func__,
+ mcc, mnc);
+
+ rc = 0;
+ goto complete;
+
+error:
+ if (*plmn != NULL) {
+ free(*plmn);
+ *plmn = NULL;
+ }
+
+ if (operator_long != NULL && *operator_long != NULL) {
+ free(*operator_long);
+ *operator_long = NULL;
+ }
+
+ if (operator_short != NULL && *operator_short != NULL) {
+ free(*operator_short);
+ *operator_short = NULL;
+ }
+
+ rc = -1;
+
+complete:
+ return rc;
+}
+
+static void get_operator_name_ready(QmiClientNas *client,
+ GAsyncResult *res,
+ RIL_Token token)
+{
+ QmiMessageNasGetOperatorNameOutput *output;
+ QmiMessageNasGetOperatorNameOutputOperatorPlmnListElement *element;
+ GError *error = NULL;
+ GArray *array;
+ char *operator[3] = { NULL };
+
+ output = qmi_client_nas_get_operator_name_finish(client, res, &error);
+ if (!output) {
+ RIL_LOGE("%s: error: operation failed: %s", __func__,
+ error->message);
+ goto error;
+ }
+
+ if (!qmi_message_nas_get_operator_name_output_get_result(output, &error)) {
+ RIL_LOGE("error: couldn't get operator name data: %s", error->message);
+ goto error;
+ }
+
+ RIL_LOGD("Successfully got operator name data");
+
+ if (qmi_message_nas_get_operator_name_output_get_operator_plmn_list(
+ output, &array, NULL)) {
+ element = &g_array_index(array, QmiMessageNasGetOperatorNameOutputOperatorPlmnListElement, 0);
+ if(qmi2ril_net_operator(element, &operator[0],
+ &operator[1], &operator[2]))
+ goto error;
+
+ RIL_LOGD("MCC/MNC: '%s', name '%s' '%s'",
+ operator[2], operator[0], operator[1]);
+ }
+
+error:
+ ril_request_complete(token, RIL_E_SUCCESS, (void *) &operator, sizeof(operator));
+
+ if (error)
+ g_error_free(error);
+ if (output)
+ qmi_message_nas_get_operator_name_output_unref(output);
+}
+
+int ril_request_operator(void *data, size_t size, RIL_Token token)
+{
+ struct ril_request *request;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_OPERATOR, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ RIL_LOGD("requesting operator name");
+ qmi_client_nas_get_operator_name(ctx->NasClient, NULL, 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)get_operator_name_ready,
+ token);
+
+ return RIL_REQUEST_HANDLED;
+}
+
+static void get_serving_system_ready(QmiClientNas *client,
+ GAsyncResult *res,
+ RIL_Token token)
+{
+ QmiMessageNasGetServingSystemOutput *output;
+ QmiNasRegistrationState registration_state;
+ QmiNasRoamingIndicatorStatus roaming;
+ QmiNasCallBarringStatus cs_call_barring, ps_call_barring;
+ GArray *data_service_capability;
+ QmiNasDataCapability data_cap;
+ guint16 lac;
+ guint32 cid;
+ unsigned char ril_status_voice = 10;
+ unsigned char ril_status_data;
+ RIL_RadioTechnology ril_technology;
+ char **voice_registration[15] = { NULL };
+ char *data_registration[5] = { NULL };
+ char **registration;
+ size_t registration_size;
+ struct ril_request *request;
+ GError *error = NULL;
+
+ output = qmi_client_nas_get_serving_system_finish(client, res, &error);
+ if (!output) {
+ RIL_LOGE("%s: error: operation failed: %s", __func__,
+ error->message);
+ goto error;
+ }
+
+ if (!qmi_message_nas_get_serving_system_output_get_result(output, &error)) {
+ RIL_LOGE("error: couldn't get serving system: %s", error->message);
+ goto error;
+ }
+
+ RIL_LOGD("Successfully got serving system");
+
+ qmi_message_nas_get_serving_system_output_get_serving_system(
+ output, &registration_state, NULL, NULL, NULL, NULL, NULL);
+
+ qmi_message_nas_get_serving_system_output_get_data_service_capability(
+ output, &data_service_capability, NULL);
+
+ qmi_message_nas_get_serving_system_output_get_roaming_indicator(
+ output, &roaming, NULL);
+ qmi_message_nas_get_serving_system_output_get_lac_3gpp(
+ output, &lac, NULL);
+ qmi_message_nas_get_serving_system_output_get_cid_3gpp(
+ output, &cid, NULL);
+
+ if(qmi_message_nas_get_serving_system_output_get_call_barring_status(
+ output, &cs_call_barring, &ps_call_barring,
+ NULL)) {
+ if ((cs_call_barring == QMI_NAS_CALL_BARRING_STATUS_NORMAL_ONLY
+ || cs_call_barring == QMI_NAS_CALL_BARRING_STATUS_NO_CALLS)
+ && (ps_call_barring == QMI_NAS_CALL_BARRING_STATUS_NORMAL_ONLY
+ || ps_call_barring == QMI_NAS_CALL_BARRING_STATUS_NO_CALLS))
+ ril_status_voice = 0;
+ }
+
+ switch (registration_state) {
+ case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED:
+ ril_status_voice += 0;
+ break;
+ case QMI_NAS_REGISTRATION_STATE_REGISTERED:
+ switch (roaming) {
+ case QMI_NAS_ROAMING_INDICATOR_STATUS_ON:
+ ril_status_voice = 5;
+ break;
+ case QMI_NAS_ROAMING_INDICATOR_STATUS_OFF:
+ ril_status_voice = 1;
+ break;
+ }
+ break;
+ case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING:
+ ril_status_voice += 2;
+ break;
+ case QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED:
+ ril_status_voice += 3;
+ break;
+ case QMI_NAS_REGISTRATION_STATE_UNKNOWN:
+ default:
+ ril_status_voice += 4;
+ }
+
+ // status for DATA_REGISTRATION_STATE doesn't include
+ // emergency status and is only 0 <= ril_status_data <= 5
+ if (ril_status_voice > 5)
+ ril_status_data = ril_status_voice - 10;
+ else
+ ril_status_data = ril_status_voice;
+
+ if (data_service_capability->len > 0)
+ data_cap = g_array_index(data_service_capability,
+ QmiNasDataCapability, 0);
+ else
+ data_cap = QMI_NAS_DATA_CAPABILITY_NONE;
+
+ switch (data_cap) {
+ case QMI_NAS_DATA_CAPABILITY_GPRS:
+ ril_technology = RADIO_TECH_GPRS;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_EDGE:
+ ril_technology = RADIO_TECH_EDGE;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_HSDPA:
+ ril_technology = RADIO_TECH_HSDPA;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_HSUPA:
+ ril_technology = RADIO_TECH_HSUPA;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_WCDMA:
+ ril_technology = RADIO_TECH_UMTS;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_EVDO_REV_0:
+ ril_technology = RADIO_TECH_EVDO_0;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_EVDO_REV_A:
+ ril_technology = RADIO_TECH_EVDO_A;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_GSM:
+ ril_technology = RADIO_TECH_GSM;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_EVDO_REV_B:
+ ril_technology = RADIO_TECH_EVDO_B;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_LTE:
+ ril_technology = RADIO_TECH_LTE;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_HSDPA_PLUS:
+ case QMI_NAS_DATA_CAPABILITY_DC_HSDPA_PLUS:
+ ril_technology = RADIO_TECH_HSPAP;
+ break;
+ case QMI_NAS_DATA_CAPABILITY_NONE:
+ default:
+ ril_technology = RADIO_TECH_UNKNOWN;
+ }
+
+ request = ril_request_find_token(token);
+
+ if (request != NULL
+ && request->request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
+ registration = (char **) &voice_registration;
+ registration_size = sizeof(voice_registration);
+ asprintf(&registration[0], "%d", ril_status_voice);
+ asprintf(&registration[1], "%x", lac);
+ asprintf(&registration[2], "%x", cid);
+ asprintf(&registration[3], "%d", ril_technology);
+ } else if (request != NULL
+ && request->request == RIL_REQUEST_DATA_REGISTRATION_STATE) {
+ registration = (char **) &data_registration;
+ registration_size = sizeof(data_registration);
+ asprintf(&registration[0], "%d", ril_status_data);
+ asprintf(&registration[1], "%x", lac);
+ asprintf(&registration[2], "%x", cid);
+ asprintf(&registration[3], "%d", ril_technology);
+ /*
+ * number of simultanious data connections
+ * TODO: make it possible to setup more using multiple
+ * devices
+ */
+ asprintf(&registration[4], "%d", 1);
+ } else
+ goto error;
+
+ ril_request_complete(token, RIL_E_SUCCESS, (void *) registration, registration_size);
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ if (error)
+ g_error_free(error);
+ if (output)
+ qmi_message_nas_get_serving_system_output_unref(output);
+}
+
+int ril_request_registration_state(void *data, size_t size,
+ RIL_Token token)
+{
+ struct ril_request *request;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_VOICE_REGISTRATION_STATE, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_DATA_REGISTRATION_STATE, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ qmi_client_nas_get_serving_system(ctx->NasClient, NULL, 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)get_serving_system_ready,
+ token);
+
+ return RIL_REQUEST_HANDLED;
+}