gsm: fix CSCS=? parsing and add testcases

Some devices (at least one Blackberry we know about) don't include
the () around the response.  Handle that and add testcases for it.
This commit is contained in:
Dan Williams
2010-04-09 13:50:45 -07:00
parent b51a9d27e5
commit 0d381e2f11
6 changed files with 151 additions and 55 deletions

View File

@@ -9,7 +9,9 @@ libmodem_helpers_la_SOURCES = \
mm-errors.c \ mm-errors.c \
mm-errors.h \ mm-errors.h \
mm-modem-helpers.c \ mm-modem-helpers.c \
mm-modem-helpers.h mm-modem-helpers.h \
mm-charsets.c \
mm-charsets.h
sbin_PROGRAMS = modem-manager sbin_PROGRAMS = modem-manager
@@ -58,8 +60,6 @@ modem_manager_SOURCES = \
main.c \ main.c \
mm-callback-info.c \ mm-callback-info.c \
mm-callback-info.h \ mm-callback-info.h \
mm-charsets.c \
mm-charsets.h \
$(auth_sources) \ $(auth_sources) \
mm-manager.c \ mm-manager.c \
mm-manager.h \ mm-manager.h \

View File

@@ -23,21 +23,22 @@
typedef struct { typedef struct {
const char *gsm_name; const char *gsm_name;
const char *other_name;
const char *iconv_from_name; const char *iconv_from_name;
const char *iconv_to_name; const char *iconv_to_name;
MMModemCharset charset; MMModemCharset charset;
} CharsetEntry; } CharsetEntry;
static CharsetEntry charset_map[] = { static CharsetEntry charset_map[] = {
{ "UTF-8", "UTF-8", "UTF-8//TRANSLIT", MM_MODEM_CHARSET_UTF8 }, { "UTF-8", "UTF8", "UTF-8", "UTF-8//TRANSLIT", MM_MODEM_CHARSET_UTF8 },
{ "UCS2", "UCS-2BE", "UCS-2BE//TRANSLIT", MM_MODEM_CHARSET_UCS2 }, { "UCS2", NULL, "UCS-2BE", "UCS-2BE//TRANSLIT", MM_MODEM_CHARSET_UCS2 },
{ "IRA", "ASCII", "ASCII//TRANSLIT", MM_MODEM_CHARSET_IRA }, { "IRA", "ASCII", "ASCII", "ASCII//TRANSLIT", MM_MODEM_CHARSET_IRA },
{ "GSM", NULL, NULL, MM_MODEM_CHARSET_GSM }, { "GSM", NULL, NULL, NULL, MM_MODEM_CHARSET_GSM },
{ "8859-1", "ISO8859-1", "ISO8859-1//TRANSLIT", MM_MODEM_CHARSET_8859_1 }, { "8859-1", NULL, "ISO8859-1", "ISO8859-1//TRANSLIT", MM_MODEM_CHARSET_8859_1 },
{ "PCCP437", NULL, NULL, MM_MODEM_CHARSET_PCCP437 }, { "PCCP437", NULL, NULL, NULL, MM_MODEM_CHARSET_PCCP437 },
{ "PCDN", NULL, NULL, MM_MODEM_CHARSET_PCDN }, { "PCDN", NULL, NULL, NULL, MM_MODEM_CHARSET_PCDN },
{ "HEX", NULL, NULL, MM_MODEM_CHARSET_HEX }, { "HEX", NULL, NULL, NULL, MM_MODEM_CHARSET_HEX },
{ NULL, NULL, NULL, MM_MODEM_CHARSET_UNKNOWN } { NULL, NULL, NULL, NULL, MM_MODEM_CHARSET_UNKNOWN }
}; };
const char * const char *
@@ -66,6 +67,8 @@ mm_modem_charset_from_string (const char *string)
while (iter->gsm_name) { while (iter->gsm_name) {
if (strcasestr (string, iter->gsm_name)) if (strcasestr (string, iter->gsm_name))
return iter->charset; return iter->charset;
if (iter->other_name && strcasestr (string, iter->other_name))
return iter->charset;
iter++; iter++;
} }
return MM_MODEM_CHARSET_UNKNOWN; return MM_MODEM_CHARSET_UNKNOWN;

View File

@@ -2676,9 +2676,6 @@ get_charsets_done (MMAtSerialPort *port,
{ {
MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMGenericGsmPrivate *priv; MMGenericGsmPrivate *priv;
GRegex *r = NULL;
GMatchInfo *match_info;
const char *p;
info->error = mm_modem_check_removed (info->modem, error); info->error = mm_modem_check_removed (info->modem, error);
if (info->error) { if (info->error) {
@@ -2688,41 +2685,13 @@ get_charsets_done (MMAtSerialPort *port,
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
/* Find the first '(' */
p = strchr (response->str, '(');
if (!p)
goto done;
p++;
/* Now parse each charset */
r = g_regex_new ("\\s*([^,\\)]+)\\s*", 0, 0, NULL);
if (!r)
goto done;
if (!g_regex_match_full (r, p, strlen (p), 0, 0, &match_info, NULL))
goto done;
priv->charsets = MM_MODEM_CHARSET_UNKNOWN; priv->charsets = MM_MODEM_CHARSET_UNKNOWN;
if (!mm_gsm_parse_cscs_support_response (response->str, &priv->charsets)) {
while (g_match_info_matches (match_info)) {
char *str;
str = g_match_info_fetch (match_info, 1);
priv->charsets |= mm_modem_charset_from_string (str);
g_free (str);
g_match_info_next (match_info, NULL);
}
g_match_info_free (match_info);
mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->charsets), NULL);
done:
if (!info->error && !priv->charsets) {
info->error = g_error_new_literal (MM_MODEM_ERROR, info->error = g_error_new_literal (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL, MM_MODEM_ERROR_GENERAL,
"Failed to parse the supported character sets response"); "Failed to parse the supported character sets response");
} } else
mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->charsets), NULL);
mm_callback_info_schedule (info); mm_callback_info_schedule (info);
} }

View File

@@ -23,6 +23,22 @@
#include "mm-errors.h" #include "mm-errors.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
const char *
mm_strip_tag (const char *str, const char *cmd)
{
const char *p = str;
if (p) {
if (!strncmp (p, cmd, strlen (cmd)))
p += strlen (cmd);
while (isspace (*p))
p++;
}
return p;
}
/*************************************************************************/
static void static void
save_scan_value (GHashTable *hash, const char *key, GMatchInfo *info, guint32 num) save_scan_value (GHashTable *hash, const char *key, GMatchInfo *info, guint32 num)
{ {
@@ -702,17 +718,55 @@ mm_cdma_parse_speri_response (const char *reply,
/*************************************************************************/ /*************************************************************************/
const char * gboolean
mm_strip_tag (const char *str, const char *cmd) mm_gsm_parse_cscs_support_response (const char *reply,
MMModemCharset *out_charsets)
{ {
const char *p = str; MMModemCharset charsets = MM_MODEM_CHARSET_UNKNOWN;
GRegex *r;
GMatchInfo *match_info;
char *p, *str;
gboolean success = FALSE;
if (p) { g_return_val_if_fail (reply != NULL, FALSE);
if (!strncmp (p, cmd, strlen (cmd))) g_return_val_if_fail (out_charsets != NULL, FALSE);
p += strlen (cmd);
while (isspace (*p)) /* Find the first '(' or '"'; the general format is:
p++; *
* +CSCS: ("IRA","GSM","UCS2")
*
* but some devices (some Blackberries) don't include the ().
*/
p = strchr (reply, '(');
if (p)
p++;
else {
p = strchr (reply, '"');
if (!p)
return FALSE;
} }
return p;
/* Now parse each charset */
r = g_regex_new ("\\s*([^,\\)]+)\\s*", 0, 0, NULL);
if (!r)
return FALSE;
if (g_regex_match_full (r, p, strlen (p), 0, 0, &match_info, NULL)) {
while (g_match_info_matches (match_info)) {
str = g_match_info_fetch (match_info, 1);
charsets |= mm_modem_charset_from_string (str);
g_free (str);
g_match_info_next (match_info, NULL);
success = TRUE;
}
g_match_info_free (match_info);
}
g_regex_unref (r);
if (success)
*out_charsets = charsets;
return success;
} }

View File

@@ -18,6 +18,7 @@
#define MM_MODEM_HELPERS_H #define MM_MODEM_HELPERS_H
#include "mm-modem-cdma.h" #include "mm-modem-cdma.h"
#include "mm-charsets.h"
#define MM_SCAN_TAG_STATUS "status" #define MM_SCAN_TAG_STATUS "status"
#define MM_SCAN_TAG_OPER_LONG "operator-long" #define MM_SCAN_TAG_OPER_LONG "operator-long"
@@ -51,5 +52,8 @@ gboolean mm_cdma_parse_speri_response (const char *reply,
gboolean *out_roaming, gboolean *out_roaming,
const char **out_desc); const char **out_desc);
gboolean mm_gsm_parse_cscs_support_response (const char *reply,
MMModemCharset *out_charsets);
#endif /* MM_MODEM_HELPERS_H */ #endif /* MM_MODEM_HELPERS_H */

View File

@@ -690,6 +690,67 @@ test_creg_cgreg_multi2_unsolicited (void *f, gpointer d)
test_creg_match ("Multi CREG/CGREG #2", FALSE, reply, data, &result); test_creg_match ("Multi CREG/CGREG #2", FALSE, reply, data, &result);
} }
static void
test_cscs_icon225_support_response (void *f, gpointer d)
{
const char *reply = "\r\n+CSCS: (\"IRA\",\"GSM\",\"UCS2\")\r\n";
MMModemCharset charsets = MM_MODEM_CHARSET_UNKNOWN;
gboolean success;
success = mm_gsm_parse_cscs_support_response (reply, &charsets);
g_assert (success);
g_assert (charsets == (MM_MODEM_CHARSET_IRA |
MM_MODEM_CHARSET_GSM |
MM_MODEM_CHARSET_UCS2));
}
static void
test_cscs_sierra_mercury_support_response (void *f, gpointer d)
{
const char *reply = "\r\n+CSCS: (\"IRA\",\"GSM\",\"UCS2\",\"PCCP437\")\r\n";
MMModemCharset charsets = MM_MODEM_CHARSET_UNKNOWN;
gboolean success;
success = mm_gsm_parse_cscs_support_response (reply, &charsets);
g_assert (success);
g_assert (charsets == (MM_MODEM_CHARSET_IRA |
MM_MODEM_CHARSET_GSM |
MM_MODEM_CHARSET_UCS2 |
MM_MODEM_CHARSET_PCCP437));
}
static void
test_cscs_buslink_support_response (void *f, gpointer d)
{
const char *reply = "\r\n+CSCS: (\"8859-1\",\"ASCII\",\"GSM\",\"UCS2\",\"UTF8\")\r\n";
MMModemCharset charsets = MM_MODEM_CHARSET_UNKNOWN;
gboolean success;
success = mm_gsm_parse_cscs_support_response (reply, &charsets);
g_assert (success);
g_assert (charsets == (MM_MODEM_CHARSET_8859_1 |
MM_MODEM_CHARSET_IRA |
MM_MODEM_CHARSET_GSM |
MM_MODEM_CHARSET_UCS2 |
MM_MODEM_CHARSET_UTF8));
}
static void
test_cscs_blackberry_support_response (void *f, gpointer d)
{
const char *reply = "\r\n+CSCS: \"IRA\"\r\n";
MMModemCharset charsets = MM_MODEM_CHARSET_UNKNOWN;
gboolean success;
success = mm_gsm_parse_cscs_support_response (reply, &charsets);
g_assert (success);
g_assert (charsets == MM_MODEM_CHARSET_IRA);
}
static TestData * static TestData *
test_data_new (void) test_data_new (void)
{ {
@@ -775,6 +836,11 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi_unsolicited, data)); g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi_unsolicited, data));
g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi2_unsolicited, data)); g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi2_unsolicited, data));
g_test_suite_add (suite, TESTCASE (test_cscs_icon225_support_response, data));
g_test_suite_add (suite, TESTCASE (test_cscs_sierra_mercury_support_response, data));
g_test_suite_add (suite, TESTCASE (test_cscs_buslink_support_response, data));
g_test_suite_add (suite, TESTCASE (test_cscs_blackberry_support_response, data));
result = g_test_run (); result = g_test_run ();
test_data_free (data); test_data_free (data);