mbm: query supported modes to the modem with +CFUN=?
We were trying to load the generic modes supported reported by either *CNTI=2 or AT+WS46=?, so that then we could filter out the MBM-specific modes unsupported. But, this may not be ideal, as both these two commands may fail: [mm-broadband-modem.c:1612] modem_load_supported_modes(): loading supported modes... [mm-port-serial.c:1237] mm_port_serial_open(): (ttyACM1) device open count is 3 (open) [mm-port-serial.c:1294] _close_internal(): (ttyACM1) device open count is 2 (close) [mm-port-serial-at.c:440] debug_log(): (ttyACM1): --> 'AT*CNTI=2<CR>' [mm-port-serial-at.c:440] debug_log(): (ttyACM1): <-- '<CR><LF>ERROR<CR><LF>' [mm-serial-parsers.c:364] mm_serial_parser_v1_parse(): Got failure code 100: Unknown error [mm-broadband-modem.c:1546] supported_modes_cnti_ready(): Generic query of supported 3GPP networks with *CNTI failed: 'Unknown error' [mm-port-serial.c:1237] mm_port_serial_open(): (ttyACM1) device open count is 3 (open) [mm-port-serial.c:1294] _close_internal(): (ttyACM1) device open count is 2 (close) [mm-port-serial-at.c:440] debug_log(): (ttyACM1): --> 'AT+WS46=?<CR>' [mm-port-serial-at.c:440] debug_log(): (ttyACM1): <-- '<CR><LF>ERROR<CR><LF>' [mm-serial-parsers.c:364] mm_serial_parser_v1_parse(): Got failure code 100: Unknown error [mm-broadband-modem.c:1494] supported_modes_ws46_test_ready(): Generic query of supported 3GPP networks with WS46=? failed: 'Unknown error' [mm-iface-modem.c:3974] load_supported_modes_ready(): couldn't load Supported Modes: 'Couldn't retrieve supported modes' Instead, we'll ask the modem for the list of modes supported, and return that directly.
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
#include "mm-bearer-list.h"
|
#include "mm-bearer-list.h"
|
||||||
#include "mm-errors-types.h"
|
#include "mm-errors-types.h"
|
||||||
#include "mm-modem-helpers.h"
|
#include "mm-modem-helpers.h"
|
||||||
|
#include "mm-modem-helpers-mbm.h"
|
||||||
#include "mm-broadband-modem-mbm.h"
|
#include "mm-broadband-modem-mbm.h"
|
||||||
#include "mm-broadband-bearer-mbm.h"
|
#include "mm-broadband-bearer-mbm.h"
|
||||||
#include "mm-sim-mbm.h"
|
#include "mm-sim-mbm.h"
|
||||||
@@ -59,12 +60,6 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbm, mm_broadband_modem_mbm, MM_TYPE_BRO
|
|||||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
|
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
|
||||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init))
|
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init))
|
||||||
|
|
||||||
#define MBM_NETWORK_MODE_OFFLINE 0
|
|
||||||
#define MBM_NETWORK_MODE_ANY 1
|
|
||||||
#define MBM_NETWORK_MODE_LOW_POWER 4
|
|
||||||
#define MBM_NETWORK_MODE_2G 5
|
|
||||||
#define MBM_NETWORK_MODE_3G 6
|
|
||||||
|
|
||||||
#define MBM_E2NAP_DISCONNECTED 0
|
#define MBM_E2NAP_DISCONNECTED 0
|
||||||
#define MBM_E2NAP_CONNECTED 1
|
#define MBM_E2NAP_CONNECTED 1
|
||||||
#define MBM_E2NAP_CONNECTING 2
|
#define MBM_E2NAP_CONNECTING 2
|
||||||
@@ -204,59 +199,55 @@ modem_after_sim_unlock (MMIfaceModem *self,
|
|||||||
/* Load supported modes (Modem interface) */
|
/* Load supported modes (Modem interface) */
|
||||||
|
|
||||||
static GArray *
|
static GArray *
|
||||||
load_supported_modes_finish (MMIfaceModem *self,
|
load_supported_modes_finish (MMIfaceModem *_self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
|
MMBroadbandModemMbm *self = MM_BROADBAND_MODEM_MBM (_self);
|
||||||
return NULL;
|
const gchar *response;
|
||||||
|
guint32 mask = 0;
|
||||||
return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parent_load_supported_modes_ready (MMIfaceModem *self,
|
|
||||||
GAsyncResult *res,
|
|
||||||
GSimpleAsyncResult *simple)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
GArray *all;
|
|
||||||
GArray *combinations;
|
GArray *combinations;
|
||||||
GArray *filtered;
|
|
||||||
MMModemModeCombination mode;
|
MMModemModeCombination mode;
|
||||||
|
|
||||||
all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
|
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
|
||||||
if (!all) {
|
if (!response)
|
||||||
g_simple_async_result_take_error (simple, error);
|
return FALSE;
|
||||||
g_simple_async_result_complete (simple);
|
|
||||||
g_object_unref (simple);
|
if (!mm_mbm_parse_cfun_test (response, &mask, error))
|
||||||
return;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
/* Build list of combinations */
|
/* Build list of combinations */
|
||||||
combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3);
|
combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3);
|
||||||
|
|
||||||
/* 2G only */
|
/* 2G only */
|
||||||
mode.allowed = MM_MODEM_MODE_2G;
|
if (mask & (1 << MBM_NETWORK_MODE_2G)) {
|
||||||
mode.preferred = MM_MODEM_MODE_NONE;
|
mode.allowed = MM_MODEM_MODE_2G;
|
||||||
g_array_append_val (combinations, mode);
|
mode.preferred = MM_MODEM_MODE_NONE;
|
||||||
|
g_array_append_val (combinations, mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* 3G only */
|
/* 3G only */
|
||||||
mode.allowed = MM_MODEM_MODE_3G;
|
if (mask & (1 << MBM_NETWORK_MODE_3G)) {
|
||||||
mode.preferred = MM_MODEM_MODE_NONE;
|
mode.allowed = MM_MODEM_MODE_3G;
|
||||||
g_array_append_val (combinations, mode);
|
mode.preferred = MM_MODEM_MODE_NONE;
|
||||||
|
g_array_append_val (combinations, mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* 2G and 3G */
|
/* 2G and 3G */
|
||||||
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
|
if (mask & (1 << MBM_NETWORK_MODE_ANY)) {
|
||||||
mode.preferred = MM_MODEM_MODE_NONE;
|
mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
|
||||||
g_array_append_val (combinations, mode);
|
mode.preferred = MM_MODEM_MODE_NONE;
|
||||||
|
g_array_append_val (combinations, mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* Filter out those unsupported modes */
|
if (combinations->len == 0) {
|
||||||
filtered = mm_filter_supported_modes (all, combinations);
|
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
||||||
g_array_unref (all);
|
"Couldn't load any supported mode");
|
||||||
g_array_unref (combinations);
|
g_array_unref (combinations);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
|
return combinations;
|
||||||
g_simple_async_result_complete (simple);
|
|
||||||
g_object_unref (simple);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -264,14 +255,12 @@ load_supported_modes (MMIfaceModem *self,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
/* Run parent's loading */
|
mm_base_modem_at_command (MM_BASE_MODEM (self),
|
||||||
iface_modem_parent->load_supported_modes (
|
"+CFUN=?",
|
||||||
MM_IFACE_MODEM (self),
|
3,
|
||||||
(GAsyncReadyCallback)parent_load_supported_modes_ready,
|
FALSE,
|
||||||
g_simple_async_result_new (G_OBJECT (self),
|
callback,
|
||||||
callback,
|
user_data);
|
||||||
user_data,
|
|
||||||
load_supported_modes));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@@ -164,3 +164,101 @@ done:
|
|||||||
return !!*ip_config;
|
return !!*ip_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#define CFUN_TAG "+CFUN:"
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_supported_mode (guint32 *mask,
|
||||||
|
guint mode)
|
||||||
|
{
|
||||||
|
g_assert (mask);
|
||||||
|
|
||||||
|
if (mode >= 32)
|
||||||
|
g_warning ("Ignored unexpected mode in +CFUN match: %d", mode);
|
||||||
|
else
|
||||||
|
*mask |= (1 << mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
mm_mbm_parse_cfun_test (const gchar *response,
|
||||||
|
guint32 *supported_mask,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gchar **groups;
|
||||||
|
guint32 mask = 0;
|
||||||
|
|
||||||
|
g_assert (supported_mask);
|
||||||
|
|
||||||
|
if (!response || !g_str_has_prefix (response, CFUN_TAG)) {
|
||||||
|
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
||||||
|
"Missing " CFUN_TAG " prefix");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AT+CFUN=?
|
||||||
|
* +CFUN: (0,1,4-6),(0,1)
|
||||||
|
* OK
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Strip tag from response */
|
||||||
|
response = mm_strip_tag (response, CFUN_TAG);
|
||||||
|
|
||||||
|
/* Split response in (groups) */
|
||||||
|
groups = mm_split_string_groups (response);
|
||||||
|
|
||||||
|
/* First group is the one listing supported modes */
|
||||||
|
if (groups && groups[0]) {
|
||||||
|
gchar **supported_modes;
|
||||||
|
|
||||||
|
supported_modes = g_strsplit_set (groups[0], ", ", -1);
|
||||||
|
if (supported_modes) {
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; supported_modes[i]; i++) {
|
||||||
|
gchar *separator;
|
||||||
|
guint mode;
|
||||||
|
|
||||||
|
if (!supported_modes[i][0])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Check if this is a range that's being given to us */
|
||||||
|
separator = strchr (supported_modes[i], '-');
|
||||||
|
if (separator) {
|
||||||
|
gchar *first_str;
|
||||||
|
gchar *last_str;
|
||||||
|
guint first;
|
||||||
|
guint last;
|
||||||
|
|
||||||
|
*separator = '\0';
|
||||||
|
first_str = supported_modes[i];
|
||||||
|
last_str = separator + 1;
|
||||||
|
|
||||||
|
if (!mm_get_uint_from_str (first_str, &first))
|
||||||
|
g_warning ("Couldn't match range start: '%s'", first_str);
|
||||||
|
else if (!mm_get_uint_from_str (last_str, &last))
|
||||||
|
g_warning ("Couldn't match range stop: '%s'", last_str);
|
||||||
|
else if (first >= last)
|
||||||
|
g_warning ("Couldn't match range: wrong first '%s' and last '%s' items", first_str, last_str);
|
||||||
|
else {
|
||||||
|
for (mode = first; mode <= last; mode++)
|
||||||
|
add_supported_mode (&mask, mode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mm_get_uint_from_str (supported_modes[i], &mode))
|
||||||
|
g_warning ("Couldn't match mode: '%s'", supported_modes[i]);
|
||||||
|
else
|
||||||
|
add_supported_mode (&mask, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (supported_modes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_strfreev (groups);
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
*supported_mask = mask;
|
||||||
|
return !!mask;
|
||||||
|
}
|
||||||
|
@@ -24,4 +24,18 @@ gboolean mm_mbm_parse_e2ipcfg_response (const gchar *response,
|
|||||||
MMBearerIpConfig **out_ip6_config,
|
MMBearerIpConfig **out_ip6_config,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MBM_NETWORK_MODE_OFFLINE = 0,
|
||||||
|
MBM_NETWORK_MODE_ANY = 1,
|
||||||
|
MBM_NETWORK_MODE_LOW_POWER = 4,
|
||||||
|
MBM_NETWORK_MODE_2G = 5,
|
||||||
|
MBM_NETWORK_MODE_3G = 6,
|
||||||
|
} MbmNetworkMode;
|
||||||
|
|
||||||
|
/* AT+CFUN=? test parser
|
||||||
|
* Returns a bitmask, bit index set for the supported modes reported */
|
||||||
|
gboolean mm_mbm_parse_cfun_test (const gchar *response,
|
||||||
|
guint32 *supported_mask,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
#endif /* MM_MODEM_HELPERS_MBM_H */
|
#endif /* MM_MODEM_HELPERS_MBM_H */
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
#include "mm-modem-helpers.h"
|
#include "mm-modem-helpers.h"
|
||||||
#include "mm-modem-helpers-mbm.h"
|
#include "mm-modem-helpers-mbm.h"
|
||||||
|
|
||||||
|
#define ENABLE_TEST_MESSAGE_TRACES
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Test *E2IPCFG responses */
|
/* Test *E2IPCFG responses */
|
||||||
|
|
||||||
@@ -129,6 +131,63 @@ test_e2ipcfg (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Test +CFUN test responses */
|
||||||
|
|
||||||
|
#define MAX_MODES 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const gchar *str;
|
||||||
|
guint32 expected_mask;
|
||||||
|
} CfunTest;
|
||||||
|
|
||||||
|
static const CfunTest cfun_tests[] = {
|
||||||
|
{
|
||||||
|
"+CFUN: (0,1,4-6),(1-0)\r\n",
|
||||||
|
((1 << MBM_NETWORK_MODE_OFFLINE) |
|
||||||
|
(1 << MBM_NETWORK_MODE_ANY) |
|
||||||
|
(1 << MBM_NETWORK_MODE_LOW_POWER) |
|
||||||
|
(1 << MBM_NETWORK_MODE_2G) |
|
||||||
|
(1 << MBM_NETWORK_MODE_3G))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"+CFUN: (0,1,4-6)\r\n",
|
||||||
|
((1 << MBM_NETWORK_MODE_OFFLINE) |
|
||||||
|
(1 << MBM_NETWORK_MODE_ANY) |
|
||||||
|
(1 << MBM_NETWORK_MODE_LOW_POWER) |
|
||||||
|
(1 << MBM_NETWORK_MODE_2G) |
|
||||||
|
(1 << MBM_NETWORK_MODE_3G))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"+CFUN: (0,1,4)\r\n",
|
||||||
|
((1 << MBM_NETWORK_MODE_OFFLINE) |
|
||||||
|
(1 << MBM_NETWORK_MODE_ANY) |
|
||||||
|
(1 << MBM_NETWORK_MODE_LOW_POWER))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"+CFUN: (0,1)\r\n",
|
||||||
|
((1 << MBM_NETWORK_MODE_OFFLINE) |
|
||||||
|
(1 << MBM_NETWORK_MODE_ANY))
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cfun (void)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (cfun_tests); i++) {
|
||||||
|
guint32 mask;
|
||||||
|
gboolean success;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
success = mm_mbm_parse_cfun_test (cfun_tests[i].str, &mask, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (success);
|
||||||
|
g_assert_cmpuint (mask, ==, cfun_tests[i].expected_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -159,6 +218,7 @@ int main (int argc, char **argv)
|
|||||||
g_test_init (&argc, &argv, NULL);
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
g_test_add_func ("/MM/mbm/e2ipcfg", test_e2ipcfg);
|
g_test_add_func ("/MM/mbm/e2ipcfg", test_e2ipcfg);
|
||||||
|
g_test_add_func ("/MM/mbm/cfun", test_cfun);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
@@ -68,6 +68,69 @@ mm_strip_tag (const gchar *str, const gchar *cmd)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
gchar **
|
||||||
|
mm_split_string_groups (const gchar *str)
|
||||||
|
{
|
||||||
|
GPtrArray *array;
|
||||||
|
const gchar *start;
|
||||||
|
const gchar *next;
|
||||||
|
|
||||||
|
array = g_ptr_array_new ();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Manually parse splitting groups. Groups may be single elements, or otherwise
|
||||||
|
* lists given between parenthesis, e.g.:
|
||||||
|
*
|
||||||
|
* ("SM","ME"),("SM","ME"),("SM","ME")
|
||||||
|
* "SM","SM","SM"
|
||||||
|
* "SM",("SM","ME"),("SM","ME")
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Iterate string splitting groups */
|
||||||
|
for (start = str; start; start = next) {
|
||||||
|
gchar *item;
|
||||||
|
gssize len = -1;
|
||||||
|
|
||||||
|
/* skip leading whitespaces */
|
||||||
|
while (*start == ' ')
|
||||||
|
start++;
|
||||||
|
|
||||||
|
if (*start == '(') {
|
||||||
|
start++;
|
||||||
|
next = strchr (start, ')');
|
||||||
|
if (next) {
|
||||||
|
len = next - start;
|
||||||
|
next = strchr (next, ',');
|
||||||
|
if (next)
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next = strchr (start, ',');
|
||||||
|
if (next) {
|
||||||
|
len = next - start;
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
item = g_strdup (start);
|
||||||
|
else
|
||||||
|
item = g_strndup (start, len);
|
||||||
|
|
||||||
|
g_ptr_array_add (array, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array->len > 0) {
|
||||||
|
g_ptr_array_add (array, NULL);
|
||||||
|
return (gchar **) g_ptr_array_free (array, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_unref (array);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
guint
|
guint
|
||||||
mm_count_bits_set (gulong number)
|
mm_count_bits_set (gulong number)
|
||||||
{
|
{
|
||||||
@@ -1290,67 +1353,6 @@ storage_from_str (const gchar *str)
|
|||||||
return MM_SMS_STORAGE_UNKNOWN;
|
return MM_SMS_STORAGE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar **
|
|
||||||
helper_split_groups (const gchar *str)
|
|
||||||
{
|
|
||||||
GPtrArray *array;
|
|
||||||
const gchar *start;
|
|
||||||
const gchar *next;
|
|
||||||
|
|
||||||
array = g_ptr_array_new ();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Manually parse splitting groups. Groups may be single elements, or otherwise
|
|
||||||
* lists given between parenthesis, e.g.:
|
|
||||||
*
|
|
||||||
* ("SM","ME"),("SM","ME"),("SM","ME")
|
|
||||||
* "SM","SM","SM"
|
|
||||||
* "SM",("SM","ME"),("SM","ME")
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Iterate string splitting groups */
|
|
||||||
for (start = str; start; start = next) {
|
|
||||||
gchar *item;
|
|
||||||
gssize len = -1;
|
|
||||||
|
|
||||||
/* skip leading whitespaces */
|
|
||||||
while (*start == ' ')
|
|
||||||
start++;
|
|
||||||
|
|
||||||
if (*start == '(') {
|
|
||||||
start++;
|
|
||||||
next = strchr (start, ')');
|
|
||||||
if (next) {
|
|
||||||
len = next - start;
|
|
||||||
next = strchr (next, ',');
|
|
||||||
if (next)
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next = strchr (start, ',');
|
|
||||||
if (next) {
|
|
||||||
len = next - start;
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
item = g_strdup (start);
|
|
||||||
else
|
|
||||||
item = g_strndup (start, len);
|
|
||||||
|
|
||||||
g_ptr_array_add (array, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array->len > 0) {
|
|
||||||
g_ptr_array_add (array, NULL);
|
|
||||||
return (gchar **) g_ptr_array_free (array, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_ptr_array_unref (array);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mm_3gpp_parse_cpms_test_response (const gchar *reply,
|
mm_3gpp_parse_cpms_test_response (const gchar *reply,
|
||||||
GArray **mem1,
|
GArray **mem1,
|
||||||
@@ -1370,7 +1372,7 @@ mm_3gpp_parse_cpms_test_response (const gchar *reply,
|
|||||||
|
|
||||||
#define N_EXPECTED_GROUPS 3
|
#define N_EXPECTED_GROUPS 3
|
||||||
|
|
||||||
split = helper_split_groups (mm_strip_tag (reply, "+CPMS:"));
|
split = mm_split_string_groups (mm_strip_tag (reply, "+CPMS:"));
|
||||||
if (!split)
|
if (!split)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@@ -51,6 +51,8 @@ gchar *mm_strip_quotes (gchar *str);
|
|||||||
const gchar *mm_strip_tag (const gchar *str,
|
const gchar *mm_strip_tag (const gchar *str,
|
||||||
const gchar *cmd);
|
const gchar *cmd);
|
||||||
|
|
||||||
|
gchar **mm_split_string_groups (const gchar *str);
|
||||||
|
|
||||||
guint mm_count_bits_set (gulong number);
|
guint mm_count_bits_set (gulong number);
|
||||||
|
|
||||||
gchar *mm_create_device_identifier (guint vid,
|
gchar *mm_create_device_identifier (guint vid,
|
||||||
|
Reference in New Issue
Block a user