aboutsummaryrefslogtreecommitdiff
path: root/plugins/wavecom
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-04-12 22:35:58 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-05-06 15:34:13 +0200
commit6c26e90610b1e657f1675d7c097dcb797735d56a (patch)
treed0d53981727fffc211a5210b4fbfc045efc8b59b /plugins/wavecom
parent8b329c1012427f88ccedf61e4ed3d455db38baf4 (diff)
wavecom: implement custom band setting
Diffstat (limited to 'plugins/wavecom')
-rw-r--r--plugins/wavecom/mm-broadband-modem-wavecom.c212
1 files changed, 201 insertions, 11 deletions
diff --git a/plugins/wavecom/mm-broadband-modem-wavecom.c b/plugins/wavecom/mm-broadband-modem-wavecom.c
index 2668805a..9be84c09 100644
--- a/plugins/wavecom/mm-broadband-modem-wavecom.c
+++ b/plugins/wavecom/mm-broadband-modem-wavecom.c
@@ -47,18 +47,19 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemWavecom, mm_broadband_modem_wavecom, MM_
/* Setup relationship between 2G bands in the modem (identified by a
* single digit in ASCII) and the bitmask in ModemManager. */
typedef struct {
- gchar wavecom_band;
+ gchar wavecom_band;
+ guint n_mm_bands;
MMModemBand mm_bands[4];
} WavecomBand2G;
static const WavecomBand2G bands_2g[] = {
- { '0', { MM_MODEM_BAND_G850, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN }},
- { '1', { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN }},
- { '2', { MM_MODEM_BAND_DCS, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN }},
- { '3', { MM_MODEM_BAND_PCS, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN }},
- { '4', { MM_MODEM_BAND_G850, MM_MODEM_BAND_PCS, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN }},
- { '5', { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN }},
- { '6', { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_PCS, MM_MODEM_BAND_UNKNOWN, MM_MODEM_BAND_UNKNOWN }},
- { '7', { MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM }}
+ { '0', 1, { MM_MODEM_BAND_G850, 0, 0, 0 }},
+ { '1', 1, { MM_MODEM_BAND_EGSM, 0, 0, 0 }},
+ { '2', 1, { MM_MODEM_BAND_DCS, 0, 0, 0 }},
+ { '3', 1, { MM_MODEM_BAND_PCS, 0, 0, 0 }},
+ { '4', 2, { MM_MODEM_BAND_G850, MM_MODEM_BAND_PCS, 0, 0 }},
+ { '5', 2, { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, 0, 0 }},
+ { '6', 2, { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_PCS, 0, 0 }},
+ { '7', 4, { MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM }}
};
/* Setup relationship between the 3G band bitmask in the modem and the bitmask
@@ -629,9 +630,8 @@ get_2g_band_ready (MMBroadbandModemWavecom *self,
if (G_UNLIKELY (!bands_array))
bands_array = g_array_new (FALSE, FALSE, sizeof (MMModemBand));
- for (j = 0; j < 4 && bands_2g[i].mm_bands[j] != MM_MODEM_BAND_UNKNOWN; j++)
+ for (j = 0; j < bands_2g[i].n_mm_bands; j++)
g_array_append_val (bands_array, bands_2g[i].mm_bands[j]);
-
}
}
}
@@ -739,6 +739,194 @@ load_current_bands (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Set bands (Modem interface) */
+
+static gboolean
+set_bands_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+wmbs_set_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *operation_result)
+{
+ GError *error = NULL;
+
+ if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error))
+ /* Let the error be critical */
+ g_simple_async_result_take_error (operation_result, error);
+ else
+ g_simple_async_result_set_op_res_gboolean (operation_result, TRUE);
+
+ g_simple_async_result_complete (operation_result);
+ g_object_unref (operation_result);
+}
+
+static void
+set_bands_3g (MMIfaceModem *self,
+ GArray *bands_array,
+ GSimpleAsyncResult *result)
+{
+ GArray *bands_array_final;
+ guint wavecom_band = 0;
+ guint i;
+ gchar *bands_string;
+ gchar *cmd;
+
+ /* The special case of ANY should be treated separately. */
+ if (bands_array->len == 1 &&
+ g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) {
+ /* We build an array with all bands to set; so that we use the same
+ * logic to build the cinterion_band, and so that we can log the list of
+ * bands being set properly */
+ bands_array_final = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), G_N_ELEMENTS (bands_3g));
+ for (i = 0; i < G_N_ELEMENTS (bands_3g); i++)
+ g_array_append_val (bands_array_final, bands_3g[i].mm_band);
+ } else
+ bands_array_final = g_array_ref (bands_array);
+
+ for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) {
+ guint j;
+
+ for (j = 0; j < bands_array_final->len; j++) {
+ if (g_array_index (bands_array_final, MMModemBand, j) == bands_3g[i].mm_band) {
+ wavecom_band |= bands_3g[i].wavecom_band_flag;
+ break;
+ }
+ }
+ }
+
+ bands_string = mm_common_build_bands_string ((MMModemBand *)bands_array_final->data,
+ bands_array_final->len);
+ g_array_unref (bands_array_final);
+
+ if (wavecom_band == 0) {
+ g_simple_async_result_set_error (result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "The given band combination is not supported: '%s'",
+ bands_string);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ g_free (bands_string);
+ return;
+ }
+
+ mm_dbg ("Setting new bands to use: '%s'", bands_string);
+ cmd = g_strdup_printf ("+WMBS=\"%u\",1", wavecom_band);
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ cmd,
+ 3,
+ FALSE,
+ (GAsyncReadyCallback)wmbs_set_ready,
+ result);
+ g_free (cmd);
+ g_free (bands_string);
+}
+
+static void
+set_bands_2g (MMIfaceModem *self,
+ GArray *bands_array,
+ GSimpleAsyncResult *result)
+{
+ GArray *bands_array_final;
+ gchar wavecom_band = '\0';
+ guint i;
+ gchar *bands_string;
+ gchar *cmd;
+
+ /* If the iface properly checked the given list against the supported bands,
+ * it's not possible to get an array longer than 4 here. */
+ g_assert (bands_array->len <= 4);
+
+ /* The special case of ANY should be treated separately. */
+ if (bands_array->len == 1 &&
+ g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) {
+ const WavecomBand2G *all;
+
+ /* All bands is the last element in our 2G bands array */
+ all = &bands_2g[G_N_ELEMENTS (bands_2g) - 1];
+
+ /* We build an array with all bands to set; so that we use the same
+ * logic to build the cinterion_band, and so that we can log the list of
+ * bands being set properly */
+ bands_array_final = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4);
+ g_array_append_vals (bands_array_final, all->mm_bands, all->n_mm_bands);
+ } else
+ bands_array_final = g_array_ref (bands_array);
+
+ for (i = 0; wavecom_band == '\0' && i < G_N_ELEMENTS (bands_2g); i++) {
+ GArray *supported_combination;
+
+ supported_combination = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), bands_2g[i].n_mm_bands);
+ g_array_append_vals (supported_combination, bands_2g[i].mm_bands, bands_2g[i].n_mm_bands);
+
+ /* Check if the given array is exactly one of the supported combinations */
+ if (mm_common_bands_garray_cmp (bands_array_final, supported_combination))
+ wavecom_band = bands_2g[i].wavecom_band;
+
+ g_array_unref (supported_combination);
+ }
+
+ bands_string = mm_common_build_bands_string ((MMModemBand *)bands_array_final->data,
+ bands_array_final->len);
+ g_array_unref (bands_array_final);
+
+ if (wavecom_band == '\0') {
+ g_simple_async_result_set_error (result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "The given band combination is not supported: '%s'",
+ bands_string);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ g_free (bands_string);
+ return;
+ }
+
+ mm_dbg ("Setting new bands to use: '%s'", bands_string);
+ cmd = g_strdup_printf ("+WMBS=%c,1", wavecom_band);
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ cmd,
+ 3,
+ FALSE,
+ (GAsyncReadyCallback)wmbs_set_ready,
+ result);
+
+ g_free (cmd);
+ g_free (bands_string);
+}
+
+static void
+set_bands (MMIfaceModem *self,
+ GArray *bands_array,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ /* The bands that we get here are previously validated by the interface, and
+ * that means that ALL the bands given here were also given in the list of
+ * supported bands. BUT BUT, that doesn't mean that the exact list of bands
+ * will end up being valid, as not all combinations are possible. E.g,
+ * Wavecom modems supporting only 2G have specific combinations allowed.
+ */
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ set_bands);
+
+ if (mm_iface_modem_is_3g (self))
+ set_bands_3g (self, bands_array, result);
+ else
+ set_bands_2g (self, bands_array, result);
+}
+
+/*****************************************************************************/
/* Load access technologies (Modem interface) */
static gboolean
@@ -1022,6 +1210,8 @@ iface_modem_init (MMIfaceModem *iface)
iface->load_supported_bands_finish = load_supported_bands_finish;
iface->load_current_bands = load_current_bands;
iface->load_current_bands_finish = load_current_bands_finish;
+ iface->set_bands = set_bands;
+ iface->set_bands_finish = set_bands_finish;
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
iface->setup_flow_control = setup_flow_control;