diff --git a/binder.conf b/binder.conf index 8bf47b1..ccd0818 100644 --- a/binder.conf +++ b/binder.conf @@ -207,3 +207,10 @@ # Default 3 (GSM_WCDMA_AUTO) # #umtsNetworkMode=3 + +# Ignore APN errors +# +# APN attachment may fail with some specific errors. +# If you want to ignore those errors to prevent power drain, add error codes here. +# +# ignoreApnErrors=501 diff --git a/src/binder_network.c b/src/binder_network.c index 2e2052d..27fb27f 100644 --- a/src/binder_network.c +++ b/src/binder_network.c @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -136,6 +137,7 @@ typedef struct binder_network_object { gboolean force_gsm_when_radio_off; BinderDataProfileConfig data_profile_config; GSList* data_profiles; + GUtilInts* ignore_apn_errors; } BinderNetworkObject; typedef BinderBaseClass BinderNetworkObjectClass; @@ -1372,6 +1374,21 @@ binder_network_can_set_initial_attach_apn( !self->set_data_profiles_req; } +static +gboolean +binder_attach_apn_retry( + RadioRequest* req, + RADIO_TX_STATUS status, + RADIO_RESP resp, + RADIO_ERROR error, + const GBinderReader* args, + void* user_data) +{ + BinderNetworkObject* self = THIS(user_data); + + return error != RADIO_ERROR_NONE && !gutil_ints_contains(self->ignore_apn_errors, error); +} + static void binder_network_set_initial_attach_apn( @@ -1389,7 +1406,7 @@ binder_network_set_initial_attach_apn( if (iface >= RADIO_INTERFACE_1_5) { /* setInitialAttachApn_1_4(int32 serial, DataProfileInfo profile); */ req = radio_request_new2(self->g, RADIO_REQ_SET_INITIAL_ATTACH_APN_1_5, - &writer, NULL, NULL, NULL); + &writer, NULL, NULL, self); gbinder_writer_append_struct(&writer, binder_network_new_radio_data_profile_1_5(&writer, &profile, dpc), @@ -1397,7 +1414,7 @@ binder_network_set_initial_attach_apn( } else if (iface >= RADIO_INTERFACE_1_4) { /* setInitialAttachApn_1_4(int32 serial, DataProfileInfo profile); */ req = radio_request_new2(self->g, RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4, - &writer, NULL, NULL, NULL); + &writer, NULL, NULL, self); gbinder_writer_append_struct(&writer, binder_network_new_radio_data_profile_1_4(&writer, &profile, dpc), @@ -1408,7 +1425,7 @@ binder_network_set_initial_attach_apn( * bool modemCognitive, bool isRoaming); */ req = radio_request_new2(self->g, RADIO_REQ_SET_INITIAL_ATTACH_APN, - &writer, NULL, NULL, NULL); + &writer, NULL, NULL, self); gbinder_writer_append_struct(&writer, binder_network_new_radio_data_profile(&writer, &profile, dpc), @@ -1418,6 +1435,7 @@ binder_network_set_initial_attach_apn( } DBG_(self, "\"%s\"", ctx->apn); + radio_request_set_retry_func(req, binder_attach_apn_retry); radio_request_set_retry(req, BINDER_RETRY_MS, -1); radio_request_set_timeout(req, INTINITE_TIMEOUT); radio_request_drop(self->set_ia_apn_req); @@ -2237,6 +2255,7 @@ binder_network_new( self->network_mode_timeout_ms = config->network_mode_timeout_ms; self->force_gsm_when_radio_off = config->force_gsm_when_radio_off; self->data_profile_config = *dpc; + self->ignore_apn_errors = gutil_ints_ref(config->ignore_apn_errors); /* Register listeners */ self->ind_id[IND_NETWORK_STATE] = @@ -2463,6 +2482,8 @@ binder_network_object_finalize( binder_sim_settings_remove_handler(net->settings, self->settings_event_id); binder_sim_settings_unref(net->settings); + gutil_ints_unref(self->ignore_apn_errors); + g_slist_free_full(self->data_profiles, g_free); g_free(self->log_prefix); diff --git a/src/binder_plugin.c b/src/binder_plugin.c index bf8f10c..8f26b8e 100644 --- a/src/binder_plugin.c +++ b/src/binder_plugin.c @@ -137,6 +137,7 @@ static const char* const binder_radio_ifaces[] = { #define BINDER_CONF_SLOT_LTE_MODE "lteNetworkMode" #define BINDER_CONF_SLOT_UMTS_MODE "umtsNetworkMode" #define BINDER_CONF_SLOT_TECHNOLOGIES "technologies" +#define BINDER_CONF_SLOT_IGNORE_APN_ERRORS "ignoreApnErrors" /* Defaults */ #define BINDER_DEFAULT_RADIO_INTERFACE RADIO_INTERFACE_1_2 @@ -1554,6 +1555,10 @@ binder_plugin_create_slot( DBG("%s: " BINDER_CONF_SLOT_DISABLE_FEATURES " 0x%04x", group, ival); } + /* ignoreApnErrors */ + config->ignore_apn_errors = binder_plugin_config_get_ints(file, group, + BINDER_CONF_SLOT_IGNORE_APN_ERRORS); + /* deviceStateTracking */ if (ofono_conf_get_mask(file, group, BINDER_CONF_SLOT_DEVMON, &ival, @@ -1726,6 +1731,7 @@ binder_plugin_slot_free( binder_sim_settings_unref(slot->sim_settings); gutil_ints_unref(slot->config.local_hangup_reasons); gutil_ints_unref(slot->config.remote_hangup_reasons); + gutil_ints_unref(slot->config.ignore_apn_errors); gbinder_servicemanager_remove_handler(slot->svcmgr, slot->radio_watch_id); gbinder_servicemanager_cancel(slot->svcmgr, slot->list_call_id); gbinder_servicemanager_unref(slot->svcmgr); diff --git a/src/binder_types.h b/src/binder_types.h index e7756fb..82a9d5f 100644 --- a/src/binder_types.h +++ b/src/binder_types.h @@ -78,6 +78,7 @@ typedef struct binder_slot_config { BinderDataProfileConfig data_profile_config; GUtilInts* local_hangup_reasons; GUtilInts* remote_hangup_reasons; + GUtilInts* ignore_apn_errors; } BinderSlotConfig; #define BINDER_DRIVER "binder"