diff options
author | Dan Williams <dcbw@redhat.com> | 2012-07-27 11:23:54 -0500 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2012-08-03 10:53:14 -0500 |
commit | 1125f232c7516349ab7e4b14abc43b1d53433d69 (patch) | |
tree | c2318995875f84546f67b2e7ea5dd3d610d08235 | |
parent | fdbab197ad15db74975f99b2e6122029c86c5a74 (diff) |
icera: add generic band handling functions
-rw-r--r-- | plugins/mm-modem-icera.c | 189 | ||||
-rw-r--r-- | plugins/mm-modem-icera.h | 9 | ||||
-rwxr-xr-x | plugins/mm-modem-samsung-gsm.c | 162 |
3 files changed, 200 insertions, 160 deletions
diff --git a/plugins/mm-modem-icera.c b/plugins/mm-modem-icera.c index 800ccae7..cdb7ef82 100644 --- a/plugins/mm-modem-icera.c +++ b/plugins/mm-modem-icera.c @@ -32,6 +32,7 @@ #include "mm-at-serial-port.h" #include "mm-generic-gsm.h" #include "mm-modem-helpers.h" +#include "mm-utils.h" #include "mm-log.h" struct _MMModemIceraPrivate { @@ -822,6 +823,194 @@ mm_modem_icera_get_local_timestamp (MMModemIcera *self, /****************************************************************/ +typedef struct { + MMModemGsmBand band; + const char *name; +} BandTable; + +static BandTable modem_bands[] = { + /* Sort 3G first since it's preferred */ + { MM_MODEM_GSM_BAND_U2100, "FDD_BAND_I" }, + { MM_MODEM_GSM_BAND_U1900, "FDD_BAND_II" }, + /* + * Several bands are forbidden to set and will always read as + * disabled, so we won't present them to the rest of + * modemmanager. + */ + /* { MM_MODEM_GSM_BAND_U1800, "FDD_BAND_III" }, */ + /* { MM_MODEM_GSM_BAND_U17IV, "FDD_BAND_IV" }, */ + /* { MM_MODEM_GSM_BAND_U800, "FDD_BAND_VI" }, */ + { MM_MODEM_GSM_BAND_U850, "FDD_BAND_V" }, + { MM_MODEM_GSM_BAND_U900, "FDD_BAND_VIII" }, + { MM_MODEM_GSM_BAND_G850, "G850" }, + /* 2G second */ + { MM_MODEM_GSM_BAND_DCS, "DCS" }, + { MM_MODEM_GSM_BAND_EGSM, "EGSM" }, + { MM_MODEM_GSM_BAND_PCS, "PCS" }, + /* And ANY last since it's most inclusive */ + { MM_MODEM_GSM_BAND_ANY, "ANY" }, +}; + +static const char * +band_mm_to_icera (MMModemGsmBand band) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (modem_bands); i++) { + if (modem_bands[i].band == band) + return modem_bands[i].name; + } + return NULL; +} + + +static gboolean +parse_ipbm (const char *reply, MMModemGsmBand *band) +{ + GRegex *r; + GMatchInfo *info; + + g_return_val_if_fail (band != NULL, FALSE); + g_return_val_if_fail (reply != NULL, FALSE); + + /* + * Response is a number of lines of the form: + * "EGSM": 0 + * "FDD_BAND_I": 1 + * ... + * with 1 and 0 indicating whether the particular band is enabled or not. + */ + r = g_regex_new ("^\"(\\w+)\": (\\d)", + G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_ANY, + NULL); + g_assert (r != NULL); + + g_regex_match (r, reply, 0, &info); + while (g_match_info_matches (info)) { + gchar *b, *e; + + b = g_match_info_fetch (info, 1); + e = g_match_info_fetch (info, 2); + if (e[0] == '1') { + guint i; + for (i = 0 ; i < G_N_ELEMENTS (modem_bands); i++) { + if (!strcmp (b, modem_bands[i].name)) { + *band |= modem_bands[i].band; + break; + } + } + } + g_free (b); + g_free (e); + g_match_info_next (info, NULL); + } + g_match_info_free (info); + g_regex_unref (r); + + return (*band > 0 ? TRUE : FALSE); +} + +static void +get_band_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + MMModemGsmBand mm_band = MM_MODEM_GSM_BAND_UNKNOWN; + + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + else if (parse_ipbm (response->str, &mm_band)) + mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL); + + mm_callback_info_schedule (info); +} + +void +mm_modem_icera_get_band (MMModemIcera *self, + MMModemUIntFn callback, + gpointer user_data) +{ + MMAtSerialPort *port; + MMCallbackInfo *info; + + info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data); + + /* Otherwise ask the modem */ + port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error); + if (!port) { + mm_callback_info_schedule (info); + return; + } + + mm_at_serial_port_queue_command (port, "AT%IPBM?", 3, get_band_done, info); +} + +static void +set_band_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + + mm_callback_info_schedule (info); +} + +void +mm_modem_icera_set_band (MMModemIcera *self, + MMModemGsmBand band, + MMModemFn callback, + gpointer user_data) +{ + MMCallbackInfo *info; + MMAtSerialPort *port; + char *command; + const char *icera_band; + + info = mm_callback_info_new (MM_MODEM (self), callback, user_data); + + port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error); + if (!port) { + mm_callback_info_schedule (info); + return; + } + + /* TODO: Check how to pass more than one band in the same AT%%IPBM command */ + if (!utils_check_for_single_value (band)) { + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Cannot set more than one band."); + mm_callback_info_schedule (info); + return; + } + + icera_band = band_mm_to_icera (band); + if (!icera_band) { + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid band."); + mm_callback_info_schedule (info); + return; + } + + command = g_strdup_printf ("AT%%IPBM=\"%s\",1", icera_band); + mm_at_serial_port_queue_command (port, command, 3, set_band_done, info); + g_free (command); +} + +/****************************************************************/ + static void get_unlock_retries_done (MMAtSerialPort *port, GString *response, diff --git a/plugins/mm-modem-icera.h b/plugins/mm-modem-icera.h index e0c4b06e..ed6bf63b 100644 --- a/plugins/mm-modem-icera.h +++ b/plugins/mm-modem-icera.h @@ -114,5 +114,14 @@ void mm_modem_icera_get_unlock_retries (MMModemIcera *self, MMModemArrayFn callback, gpointer user_data); +void mm_modem_icera_get_band (MMModemIcera *self, + MMModemUIntFn callback, + gpointer user_data); + +void mm_modem_icera_set_band (MMModemIcera *self, + MMModemGsmBand band, + MMModemFn callback, + gpointer user_data); + #endif /* MM_MODEM_ICERA_H */ diff --git a/plugins/mm-modem-samsung-gsm.c b/plugins/mm-modem-samsung-gsm.c index 0bda8994..be2c8c7f 100755 --- a/plugins/mm-modem-samsung-gsm.c +++ b/plugins/mm-modem-samsung-gsm.c @@ -31,7 +31,6 @@ #include "mm-modem-gsm-card.h" #include "mm-log.h" #include "mm-modem-icera.h" -#include "mm-utils.h" #include "mm-modem-time.h" static void modem_init (MMModem *modem_class); @@ -53,9 +52,7 @@ G_DEFINE_TYPE_EXTENDED (MMModemSamsungGsm, mm_modem_samsung_gsm, MM_TYPE_GENERIC typedef struct { gboolean disposed; - MMModemIceraPrivate *icera; - char *band; } MMModemSamsungGsmPrivate; #define IPDPADDR_TAG "%IPDPADDR: " @@ -84,44 +81,6 @@ mm_modem_samsung_gsm_new (const char *device, return modem; } -typedef struct { - MMModemGsmBand mm; - char band[50]; -} BandTable; - -static BandTable bands[12] = { - /* Sort 3G first since it's preferred */ - { MM_MODEM_GSM_BAND_U2100, "FDD_BAND_I" }, - { MM_MODEM_GSM_BAND_U1900, "FDD_BAND_II" }, - { MM_MODEM_GSM_BAND_U1800, "FDD_BAND_III" }, - { MM_MODEM_GSM_BAND_U17IV, "FDD_BAND_IV" }, - { MM_MODEM_GSM_BAND_U850, "FDD_BAND_V" }, - { MM_MODEM_GSM_BAND_U800, "FDD_BAND_VI" }, - { MM_MODEM_GSM_BAND_U900, "FDD_BAND_VIII" }, - { MM_MODEM_GSM_BAND_G850, "G850" }, - /* 2G second */ - { MM_MODEM_GSM_BAND_DCS, "DCS" }, - { MM_MODEM_GSM_BAND_EGSM, "EGSM" }, /* 0x100 = Extended GSM, 0x200 = Primary GSM */ - { MM_MODEM_GSM_BAND_PCS, "PCS" }, - /* And ANY last since it's most inclusive */ - { MM_MODEM_GSM_BAND_ANY, "ANY" }, -}; - -static gboolean -band_mm_to_samsung (MMModemGsmBand band, MMModemGsmNetwork *modem) -{ - int i; - MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (modem); - - for (i = 0; i < sizeof (bands) / sizeof (BandTable); i++) { - if (bands[i].mm == band) { - priv->band = bands[i].band; - return TRUE; - } - } - return FALSE; -} - static void get_allowed_mode (MMGenericGsm *gsm, MMModemUIntFn callback, @@ -140,117 +99,12 @@ set_allowed_mode (MMGenericGsm *gsm, } static void -set_band_done (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) - info->error = g_error_copy (error); - - mm_callback_info_schedule (info); -} - -static void set_band (MMModemGsmNetwork *modem, MMModemGsmBand band, MMModemFn callback, gpointer user_data) { - MMCallbackInfo *info; - MMAtSerialPort *port; - char *command; - MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (modem); - - info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); - - port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error); - if (!port) { - mm_callback_info_schedule (info); - return; - } - - /* TODO: Check how to pass more than one band in the same AT%%IPBM command */ - if (!utils_check_for_single_value (band)) { - info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Cannot set more than one band."); - mm_callback_info_schedule (info); - } else if (!band_mm_to_samsung (band, modem)) { - info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid band."); - mm_callback_info_schedule (info); - } else { - mm_callback_info_set_data (info, "band", g_strdup(priv->band), NULL); - command = g_strdup_printf ("AT%%IPBM=\"%s\",1", priv->band); - mm_at_serial_port_queue_command (port, command, 3, set_band_done, info); - g_free (command); - priv->band = NULL; - } -} - -static gboolean -parse_ipbm (const char *reply, MMModemGsmBand *band) -{ - int enable[12]; - - g_return_val_if_fail (band != NULL, FALSE); - g_return_val_if_fail (reply != NULL, FALSE); - - if (sscanf (reply, "\"ANY\": %d\r\n\"EGSM\": %d\r\n\"DCS\": %d\r\n\"PCS\": %d\r\n\"G850\": %d\r\n\"FDD_BAND_I\": %d\r\n\"FDD_BAND_II\": %d\r\n\"FDD_BAND_III\": %d\r\n\"FDD_BAND_IV\": %d\r\n\"FDD_BAND_V\": %d\r\n\"FDD_BAND_VI\": %d\r\n\"FDD_BAND_VIII\": %d", &enable[0], &enable[1], &enable[2], &enable[3], &enable[4], &enable[5], &enable[6], &enable[7], &enable[8], &enable[9], &enable[10], &enable[11]) != 12) - return FALSE; - - *band = 0; - if (enable[5] == 1) - *band |= MM_MODEM_GSM_BAND_U2100; - if (enable[6] == 1) - *band |= MM_MODEM_GSM_BAND_U1900; - if (enable[7] == 1) - *band |= MM_MODEM_GSM_BAND_U1800; - if (enable[8] == 1) - *band |= MM_MODEM_GSM_BAND_U17IV; - if (enable[9] == 1) - *band |= MM_MODEM_GSM_BAND_U850; - if (enable[10] == 1) - *band |= MM_MODEM_GSM_BAND_U800; - if (enable[11] == 1) - *band |= MM_MODEM_GSM_BAND_U900; - if (enable[1] == 1) - *band |= MM_MODEM_GSM_BAND_EGSM; - if (enable[2] == 1) - *band |= MM_MODEM_GSM_BAND_DCS; - if (enable[3] == 1) - *band |= MM_MODEM_GSM_BAND_PCS; - if (enable[4] == 1) - *band |= MM_MODEM_GSM_BAND_G850; - - return (*band > 0 ? TRUE : FALSE); -} - -static void -get_band_done (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMModemGsmBand mm_band = MM_MODEM_GSM_BAND_UNKNOWN; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) - info->error = g_error_copy (error); - else if (parse_ipbm (response->str, &mm_band)) - mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL); - - mm_callback_info_schedule (info); + mm_modem_icera_set_band (MM_MODEM_ICERA (modem), band, callback, user_data); } static void @@ -258,19 +112,7 @@ get_band (MMModemGsmNetwork *modem, MMModemUIntFn callback, gpointer user_data) { - MMAtSerialPort *port; - MMCallbackInfo *info; - - info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - - /* Otherwise ask the modem */ - port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error); - if (!port) { - mm_callback_info_schedule (info); - return; - } - - mm_at_serial_port_queue_command (port, "AT%IPBM?", 3, get_band_done, info); + mm_modem_icera_get_band (MM_MODEM_ICERA (modem), callback, user_data); } static void |