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:
@@ -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 \
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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 */
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user