---
 drivers/huaweimodem/radio-settings.c |  172 ++++++++++++++++++++++++++++++++-
 1 files changed, 166 insertions(+), 6 deletions(-)

diff --git a/drivers/huaweimodem/radio-settings.c 
b/drivers/huaweimodem/radio-settings.c
index 1281d8b..d72a82c 100644
--- a/drivers/huaweimodem/radio-settings.c
+++ b/drivers/huaweimodem/radio-settings.c
@@ -43,16 +43,122 @@
 static const char *none_prefix[] = { NULL };
 static const char *syscfg_prefix[] = { "^SYSCFG:", NULL };
 
+static const unsigned int HUAWEI_BAND_ANY = 0x3FFFFFFF;
+
 struct radio_settings_data {
        GAtChat *chat;
        enum ofono_radio_access_mode mode;
+       enum ofono_radio_band_gsm band_gsm;
+       enum ofono_radio_band_umts band_umts;
        struct {
                enum ofono_radio_access_mode mode;
        } pending;
 };
 
-static ofono_bool_t syscfg_query_parse(struct radio_settings_data *rsd,
-                                       GAtResult *result)
+static unsigned int band_gsm_to_huawei(enum ofono_radio_band_gsm band)
+{
+       switch (band) {
+       case OFONO_RADIO_BAND_GSM_ANY:
+               return HUAWEI_BAND_ANY;
+       case OFONO_RADIO_BAND_GSM_850:
+               return 0x80000;
+       case OFONO_RADIO_BAND_GSM_900P:
+               return 0x200;
+       case OFONO_RADIO_BAND_GSM_900E:
+               return 0x100;
+       case OFONO_RADIO_BAND_GSM_1800:
+               return 0x80;
+       case OFONO_RADIO_BAND_GSM_1900:
+               return 0x200000;
+       default:
+               return 0;
+       }
+}
+
+static enum ofono_radio_band_gsm band_gsm_from_huawei(unsigned int band)
+{
+       switch(band) {
+       case 0x80000:
+               return OFONO_RADIO_BAND_GSM_850;
+       case 0x200:
+               return OFONO_RADIO_BAND_GSM_900P;
+       case 0x100:
+               return OFONO_RADIO_BAND_GSM_900E;
+       case 0x80:
+               return OFONO_RADIO_BAND_GSM_1800;
+       case 0x200000:
+               return OFONO_RADIO_BAND_GSM_1900;
+       default:
+               return OFONO_RADIO_BAND_GSM_ANY;
+       }
+}
+
+static unsigned int band_umts_to_huawei(enum ofono_radio_band_umts band)
+{
+       switch (band) {
+       case OFONO_RADIO_BAND_UMTS_ANY:
+               return HUAWEI_BAND_ANY;
+       case OFONO_RADIO_BAND_UMTS_850:
+               return 0x4000000;
+       case OFONO_RADIO_BAND_UMTS_900:
+               return 0x20000;
+       case OFONO_RADIO_BAND_UMTS_1900:
+               return 0x800000;
+       case OFONO_RADIO_BAND_UMTS_2100:
+               return 0x400000;
+       default:
+               return 0;
+       }
+}
+
+static enum ofono_radio_band_umts band_umts_from_huawei(unsigned int band)
+{
+       switch(band) {
+       case 0x4000000:
+               return OFONO_RADIO_BAND_UMTS_850;
+       case 0x20000:
+               return OFONO_RADIO_BAND_UMTS_900;
+       case 0x800000:
+               return OFONO_RADIO_BAND_UMTS_1900;
+       case 0x400000:
+               return OFONO_RADIO_BAND_UMTS_2100;
+       default:
+               return OFONO_RADIO_BAND_UMTS_ANY;
+       }
+}
+
+static ofono_bool_t syscfg_query_parse_band(struct radio_settings_data *rsd,
+                                               GAtResult *result)
+{
+       GAtResultIter iter;
+       int mode, acq_order, len;
+       unsigned int band;
+       const guint8 *band_str;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (g_at_result_iter_next(&iter, "^SYSCFG:") == FALSE)
+               return FALSE;
+
+       if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
+               return FALSE;
+
+       if (g_at_result_iter_next_number(&iter, &acq_order) == FALSE)
+               return FALSE;
+
+       if (g_at_result_iter_next_hexstring(&iter, &band_str, &len) == FALSE)
+               return FALSE;
+
+       sscanf((const char *) band_str, "%x", &band);
+
+       rsd->band_gsm = band_gsm_from_huawei(band);
+       rsd->band_umts = band_umts_from_huawei(band);
+
+       return TRUE;
+}
+
+static ofono_bool_t syscfg_query_parse_mode(struct radio_settings_data *rsd,
+                                               GAtResult *result)
 {
        GAtResultIter iter;
        int value;
@@ -82,6 +188,14 @@ static ofono_bool_t syscfg_query_parse(struct 
radio_settings_data *rsd,
        return TRUE;
 }
 
+static void huawei_query_band(struct ofono_radio_settings *rs,
+                       ofono_radio_settings_band_query_cb_t cb, void *data)
+{
+       struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+
+       CALLBACK_WITH_SUCCESS(cb, rsd->band_gsm, rsd->band_umts, data);
+}
+
 static void huawei_query_rat_mode_cb(gboolean ok, GAtResult *result,
                                        gpointer user_data)
 {
@@ -97,7 +211,7 @@ static void huawei_query_rat_mode_cb(gboolean ok, GAtResult 
*result,
                return;
        }
 
-       if (!syscfg_query_parse(rsd, result)) {
+       if (!syscfg_query_parse_mode(rsd, result)) {
                CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
                return;
        }
@@ -143,6 +257,7 @@ static void huawei_set_rat_mode(struct ofono_radio_settings 
*rs,
        struct cb_data *cbd = cb_data_new(cb, data);
        char buf[40];
        unsigned int value = 2, acq_order = 0;
+       unsigned int band = HUAWEI_BAND_ANY;
 
        switch (mode) {
        case OFONO_RADIO_ACCESS_MODE_ANY:
@@ -152,17 +267,19 @@ static void huawei_set_rat_mode(struct 
ofono_radio_settings *rs,
        case OFONO_RADIO_ACCESS_MODE_GSM:
                value = 13;
                acq_order = 1;
+               band = band_gsm_to_huawei(rsd->band_gsm);
                break;
        case OFONO_RADIO_ACCESS_MODE_UMTS:
                value = 14;
                acq_order = 2;
+               band = band_umts_to_huawei(rsd->band_umts);
                break;
        case OFONO_RADIO_ACCESS_MODE_LTE:
                goto error;
        }
 
-       snprintf(buf, sizeof(buf), "AT^SYSCFG=%u,%u,3FFFFFFF,2,4",
-                       value, acq_order);
+       snprintf(buf, sizeof(buf), "AT^SYSCFG=%u,%u,%x,2,4",
+                       value, acq_order, band);
 
        rsd->pending.mode = mode;
        cbd->user = rsd;
@@ -176,6 +293,44 @@ error:
        g_free(cbd);
 }
 
+static void huawei_set_band(struct ofono_radio_settings *rs,
+                       enum ofono_radio_band_gsm band_gsm,
+                       enum ofono_radio_band_umts band_umts,
+                       ofono_radio_settings_band_set_cb_t cb, void *data)
+{
+       struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+       ofono_bool_t change_mode = FALSE;
+
+       if (!band_gsm_to_huawei(band_gsm))
+               goto error;
+
+       if (!band_umts_to_huawei(band_umts))
+               goto error;
+
+       if (rsd->mode == OFONO_RADIO_ACCESS_MODE_ANY ||
+                       (rsd->mode == OFONO_RADIO_ACCESS_MODE_GSM &&
+                        rsd->band_gsm != band_gsm) ||
+                       (rsd->mode == OFONO_RADIO_ACCESS_MODE_UMTS &&
+                        rsd->band_umts != band_umts))
+               change_mode = TRUE;
+
+       rsd->band_gsm = band_gsm;
+       rsd->band_umts = band_umts;
+
+       if (!change_mode) {
+               CALLBACK_WITH_SUCCESS(cb, data);
+
+               return;
+       }
+
+       huawei_set_rat_mode(rs, rsd->mode, cb, data);
+
+       return;
+
+error:
+       CALLBACK_WITH_FAILURE(cb, data);
+}
+
 static void syscfg_support_cb(gboolean ok, GAtResult *result,
                                gpointer user_data)
 {
@@ -185,7 +340,10 @@ static void syscfg_support_cb(gboolean ok, GAtResult 
*result,
        if (!ok)
                goto error_not_supported;
 
-       if (!syscfg_query_parse(rsd, result))
+       if (!syscfg_query_parse_mode(rsd, result))
+               goto error_parsing;
+
+       if (!syscfg_query_parse_band(rsd, result))
                goto error_parsing;
 
        ofono_radio_settings_register(rs);
@@ -236,6 +394,8 @@ static struct ofono_radio_settings_driver driver = {
        .remove                 = huawei_radio_settings_remove,
        .query_rat_mode         = huawei_query_rat_mode,
        .set_rat_mode           = huawei_set_rat_mode,
+       .query_band             = huawei_query_band,
+       .set_band               = huawei_set_band,
 };
 
 void huawei_radio_settings_init()
-- 
1.7.3.3

_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to