aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2014-02-05 08:38:27 +0100
committerGuido Günther <agx@sigxcpu.org>2014-02-05 08:38:27 +0100
commit14d771b90f5a7d3887e5e900d1fb4737477ad305 (patch)
treef382e3359d20916ae60d28361e59635e373224f8 /plugins
parenta09050a7f63a262bf90dcb1c7a41f9cfd205db43 (diff)
Imported Upstream version 0.5.2.0upstream/0.5.2.0
Diffstat (limited to 'plugins')
-rw-r--r--plugins/77-mm-ericsson-mbm.rules27
-rw-r--r--plugins/77-mm-nokia-port-types.rules39
-rw-r--r--plugins/Makefile.am6
-rw-r--r--plugins/Makefile.in10
-rw-r--r--plugins/mm-modem-anydata-cdma.c6
-rw-r--r--plugins/mm-modem-hso.c8
-rw-r--r--plugins/mm-modem-huawei-gsm.c99
-rw-r--r--plugins/mm-modem-mbm.c4
-rw-r--r--plugins/mm-modem-nokia.c9
-rw-r--r--plugins/mm-modem-novatel-cdma.c16
-rw-r--r--plugins/mm-modem-novatel-gsm.c3
-rwxr-xr-xplugins/mm-modem-samsung-gsm.c4
-rw-r--r--plugins/mm-modem-sierra-gsm.c261
-rw-r--r--plugins/mm-modem-wavecom-gsm.c121
-rw-r--r--plugins/mm-modem-x22x-gsm.c3
-rw-r--r--plugins/mm-modem-zte.c6
-rw-r--r--plugins/mm-plugin-huawei.c237
-rw-r--r--plugins/mm-plugin-longcheer.c3
-rw-r--r--plugins/mm-plugin-nokia.c33
-rw-r--r--plugins/mm-plugin-x22x.c3
20 files changed, 635 insertions, 263 deletions
diff --git a/plugins/77-mm-ericsson-mbm.rules b/plugins/77-mm-ericsson-mbm.rules
index 8c03acf..897bd5c 100644
--- a/plugins/77-mm-ericsson-mbm.rules
+++ b/plugins/77-mm-ericsson-mbm.rules
@@ -30,6 +30,27 @@ ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190b", ENV{ID_MM_ERICSSON_MBM}="1"
ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190d", ENV{ID_MM_ERICSSON_MBM}="1"
ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1911", ENV{ID_MM_ERICSSON_MBM}="1"
+# Ericsson H5321gw
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1919", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson H5321w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191d", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson F5321gw
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1917", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson F5321w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191b", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson C5621gw
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191f", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson C5621w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1921", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson C3304w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1928", ENV{ID_MM_ERICSSON_MBM}="1"
+
# Sony-Ericsson MD300
ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d0cf", ENV{ID_MM_ERICSSON_MBM}="1"
@@ -39,6 +60,9 @@ ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d0e1", ENV{ID_MM_ERICSSON_MBM}="1"
# Sony-Ericsson MD400G
ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d103", ENV{ID_MM_ERICSSON_MBM}="1"
+# Dell 5560
+ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818e", ENV{ID_MM_ERICSSON_MBM}="1"
+
# Dell 5550
ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818d", ENV{ID_MM_ERICSSON_MBM}="1"
@@ -59,6 +83,9 @@ ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="271d", ENV{ID_MM_ERICSSON_MBM}="1"
# HP hs2320 Mobile Broadband Module
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="261d", ENV{ID_MM_ERICSSON_MBM}="1"
+# HP hs2340 Mobile Broadband Module
+ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3a1d", ENV{ID_MM_ERICSSON_MBM}="1"
+
# HP lc2000 Mobile Broadband Module
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="301d", ENV{ID_MM_ERICSSON_MBM}="1"
diff --git a/plugins/77-mm-nokia-port-types.rules b/plugins/77-mm-nokia-port-types.rules
new file mode 100644
index 0000000..560f3ce
--- /dev/null
+++ b/plugins/77-mm-nokia-port-types.rules
@@ -0,0 +1,39 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add|change", GOTO="mm_nokia_port_types_end"
+SUBSYSTEM!="tty", GOTO="mm_nokia_port_types_end"
+
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="0421", GOTO="mm_nokia_port_types_vendorcheck"
+GOTO="mm_nokia_port_types_end"
+
+LABEL="mm_nokia_port_types_vendorcheck"
+SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
+
+# For Nokia Internet Sticks (CS-xx) the modem/PPP port appears to always be USB interface 1
+
+ATTRS{idProduct}=="060D", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0611", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="061A", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="061B", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="061F", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0620", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0623", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0624", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0625", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="062A", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="062E", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="062F", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+LABEL="mm_nokia_port_types_end"
+
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 47fc3b0..2b71246 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -189,6 +189,9 @@ libmm_plugin_sierra_la_LDFLAGS = \
-module \
-avoid-version
+libmm_plugin_sierra_la_LIBADD = \
+ $(builddir)/libicera-utils.la
+
# Wavecom (Sierra Airlink)
libmm_plugin_wavecom_la_SOURCES = \
@@ -384,7 +387,8 @@ udevrules_DATA = \
77-mm-zte-port-types.rules \
77-mm-longcheer-port-types.rules \
77-mm-simtech-port-types.rules \
- 77-mm-x22x-port-types.rules
+ 77-mm-x22x-port-types.rules \
+ 77-mm-nokia-port-types.rules
BUILT_SOURCES = \
mm-modem-gsm-hso-glue.h
diff --git a/plugins/Makefile.in b/plugins/Makefile.in
index df6b5e3..b2dea3f 100644
--- a/plugins/Makefile.in
+++ b/plugins/Makefile.in
@@ -46,7 +46,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -204,7 +204,7 @@ libmm_plugin_samsung_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libmm_plugin_samsung_la_LDFLAGS) \
$(LDFLAGS) -o $@
-libmm_plugin_sierra_la_LIBADD =
+libmm_plugin_sierra_la_DEPENDENCIES = $(builddir)/libicera-utils.la
am_libmm_plugin_sierra_la_OBJECTS = \
libmm_plugin_sierra_la-mm-plugin-sierra.lo \
libmm_plugin_sierra_la-mm-modem-sierra-gsm.lo \
@@ -648,6 +648,9 @@ libmm_plugin_sierra_la_LDFLAGS = \
-module \
-avoid-version
+libmm_plugin_sierra_la_LIBADD = \
+ $(builddir)/libicera-utils.la
+
# Wavecom (Sierra Airlink)
libmm_plugin_wavecom_la_SOURCES = \
@@ -843,7 +846,8 @@ udevrules_DATA = \
77-mm-zte-port-types.rules \
77-mm-longcheer-port-types.rules \
77-mm-simtech-port-types.rules \
- 77-mm-x22x-port-types.rules
+ 77-mm-x22x-port-types.rules \
+ 77-mm-nokia-port-types.rules
BUILT_SOURCES = \
mm-modem-gsm-hso-glue.h
diff --git a/plugins/mm-modem-anydata-cdma.c b/plugins/mm-modem-anydata-cdma.c
index 7b6b37a..d26d3ec 100644
--- a/plugins/mm-modem-anydata-cdma.c
+++ b/plugins/mm-modem-anydata-cdma.c
@@ -183,6 +183,9 @@ evdo_state_done (MMAtSerialPort *port,
}
}
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+
done:
mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, reg_state);
mm_callback_info_schedule (info);
@@ -254,6 +257,9 @@ state_done (MMAtSerialPort *port,
}
}
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+
mm_generic_cdma_query_reg_state_set_callback_1x_state (info, reg_state);
/* Try for EVDO state too */
diff --git a/plugins/mm-modem-hso.c b/plugins/mm-modem-hso.c
index e3d4dce..5d4201c 100644
--- a/plugins/mm-modem-hso.c
+++ b/plugins/mm-modem-hso.c
@@ -778,7 +778,12 @@ grab_port (MMModem *modem,
goto out;
if (MM_IS_AT_SERIAL_PORT (port)) {
- g_object_set (G_OBJECT (port), MM_SERIAL_PORT_SEND_DELAY, (guint64) 0, NULL);
+ g_object_set (G_OBJECT (port),
+ MM_SERIAL_PORT_SEND_DELAY, (guint64) 0,
+ /* built-in echo removal conflicts with unsolicited _OWANCALL
+ * messages, which are not <CR><LF> prefixed. */
+ MM_AT_SERIAL_PORT_REMOVE_ECHO, FALSE,
+ NULL);
if (ptype == MM_PORT_TYPE_PRIMARY) {
GRegex *regex;
@@ -854,4 +859,3 @@ mm_modem_hso_class_init (MMModemHsoClass *klass)
gsm_class->get_allowed_mode = get_allowed_mode;
gsm_class->get_access_technology = get_access_technology;
}
-
diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c
index 5f4c2fb..4fc3c3f 100644
--- a/plugins/mm-modem-huawei-gsm.c
+++ b/plugins/mm-modem-huawei-gsm.c
@@ -599,9 +599,9 @@ send_huawei_cpin_done (MMAtSerialPort *port,
mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
- g_match_info_free (match_info);
-
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_serial_port_close (MM_SERIAL_PORT (port));
@@ -729,82 +729,6 @@ handle_status_change (MMAtSerialPort *port,
/*****************************************************************************/
-static void
-do_enable_power_up_done (MMGenericGsm *gsm,
- GString *response,
- GError *error,
- MMCallbackInfo *info)
-{
- if (!error) {
- MMAtSerialPort *primary;
-
- /* Enable unsolicited result codes */
- primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY);
- g_assert (primary);
-
- mm_at_serial_port_queue_command (primary, "^CURC=1", 5, NULL, NULL);
- }
-
- /* Chain up to parent */
- MM_GENERIC_GSM_CLASS (mm_modem_huawei_gsm_parent_class)->do_enable_power_up_done (gsm, NULL, error, info);
-}
-
-/*****************************************************************************/
-
-static void
-disable_unsolicited_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;
-
- /* Ignore all errors */
- mm_callback_info_schedule (info);
-}
-
-static void
-invoke_call_parent_disable_fn (MMCallbackInfo *info)
-{
- /* Note: we won't call the parent disable if info->modem is no longer
- * valid. The invoke is called always once the info gets scheduled, which
- * may happen during removed modem detection. */
- if (info->modem) {
- MMModem *parent_modem_iface;
-
- parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (info->modem));
- parent_modem_iface->disable (info->modem, (MMModemFn)info->callback, info->user_data);
- }
-}
-
-static void
-disable (MMModem *modem,
- MMModemFn callback,
- gpointer user_data)
-{
- MMAtSerialPort *primary;
- MMCallbackInfo *info;
-
- info = mm_callback_info_new_full (modem,
- invoke_call_parent_disable_fn,
- (GCallback)callback,
- user_data);
-
- primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
- g_assert (primary);
-
- /* Turn off unsolicited responses */
- mm_at_serial_port_queue_command (primary, "^CURC=0", 5, disable_unsolicited_done, info);
-}
-
-/*****************************************************************************/
-
static gboolean
grab_port (MMModem *modem,
const char *subsys,
@@ -888,6 +812,16 @@ ussd_encode (MMModemGsmUssd *self, const char* command, guint *scheme)
*scheme = MM_MODEM_GSM_USSD_SCHEME_7BIT;
gsm = mm_charset_utf8_to_unpacked_gsm (command, &len);
+
+ /* If command is a multiple of 7 characters long, Huawei firmwares
+ * apparently want that padded. Maybe all modems?
+ */
+ if (len % 7 == 0) {
+ gsm = g_realloc (gsm, len + 1);
+ gsm[len] = 0x0d;
+ len++;
+ }
+
packed = gsm_pack (gsm, len, 0, &packed_len);
hex = utils_bin2hexstr (packed, packed_len);
g_free (packed);
@@ -906,8 +840,11 @@ ussd_decode (MMModemGsmUssd *self, const char* reply, guint scheme)
guint32 unpacked_len;
bin = utils_hexstr2bin (reply, &bin_len);
- unpacked = gsm_unpack ((guint8*)bin, bin_len, 0, &unpacked_len);
- utf8 = (char*)mm_charset_gsm_unpacked_to_utf8 (unpacked, unpacked_len);
+ unpacked = gsm_unpack ((guint8*) bin, (bin_len * 8) / 7, 0, &unpacked_len);
+ /* if the last character in a 7-byte block is padding, then drop it */
+ if ((bin_len % 7 == 0) && (unpacked[unpacked_len - 1] == 0x0d))
+ unpacked_len--;
+ utf8 = (char*) mm_charset_gsm_unpacked_to_utf8 (unpacked, unpacked_len);
g_free (bin);
g_free (unpacked);
@@ -920,7 +857,6 @@ static void
modem_init (MMModem *modem_class)
{
modem_class->grab_port = grab_port;
- modem_class->disable = disable;
}
static void
@@ -960,6 +896,5 @@ mm_modem_huawei_gsm_class_init (MMModemHuaweiGsmClass *klass)
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;
gsm_class->get_access_technology = get_access_technology;
- gsm_class->do_enable_power_up_done = do_enable_power_up_done;
}
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index 7aa8a01..ab39ff6 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -730,7 +730,9 @@ enap_poll_response (MMAtSerialPort *port,
count = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mbm-enap-poll-count"));
- if (sscanf (response->str, "*ENAP: %d", &state) == 1 && state == 1) {
+ if ( response
+ && sscanf (response->str, "*ENAP: %d", &state) == 1
+ && state == 1) {
/* Success! Connected... */
mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), NULL, info);
return;
diff --git a/plugins/mm-modem-nokia.c b/plugins/mm-modem-nokia.c
index 56f4c1b..9476f61 100644
--- a/plugins/mm-modem-nokia.c
+++ b/plugins/mm-modem-nokia.c
@@ -120,6 +120,11 @@ get_property (GObject *object, guint prop_id,
case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
g_value_set_string (value, "");
break;
+ case MM_GENERIC_GSM_PROP_INIT_CMD:
+ /* When initializing a Nokia phone, first enable the echo,
+ * and then disable it, so that we get it properly disabled */
+ g_value_set_string (value, "Z E1 E0 V1");
+ break;
default:
break;
}
@@ -136,6 +141,10 @@ mm_modem_nokia_class_init (MMModemNokiaClass *klass)
object_class->set_property = set_property;
g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_INIT_CMD,
+ MM_GENERIC_GSM_INIT_CMD);
+
+ g_object_class_override_property (object_class,
MM_GENERIC_GSM_PROP_POWER_UP_CMD,
MM_GENERIC_GSM_POWER_UP_CMD);
diff --git a/plugins/mm-modem-novatel-cdma.c b/plugins/mm-modem-novatel-cdma.c
index c1f4151..77d6bee 100644
--- a/plugins/mm-modem-novatel-cdma.c
+++ b/plugins/mm-modem-novatel-cdma.c
@@ -181,7 +181,7 @@ get_signal_quality (MMModemCdma *modem,
/*****************************************************************************/
static void
-parse_modem_snapshot (MMCallbackInfo *info, QCDMResult *result)
+parse_modem_snapshot (MMCallbackInfo *info, QcdmResult *result)
{
MMModemCdmaRegistrationState evdo_state, cdma1x_state, new_state;
guint8 eri = 0;
@@ -193,7 +193,7 @@ parse_modem_snapshot (MMCallbackInfo *info, QCDMResult *result)
cdma1x_state = mm_generic_cdma_query_reg_state_get_callback_1x_state (info);
/* Roaming? */
- if (qcdm_result_get_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, &eri)) {
+ if (qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, &eri)) {
char *str;
gboolean roaming = FALSE;
@@ -216,7 +216,7 @@ reg_nwsnap_6500_cb (MMQcdmSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = user_data;
- QCDMResult *result;
+ QcdmResult *result;
if (!error) {
result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const char *) response->data, response->len, NULL);
@@ -235,20 +235,18 @@ reg_nwsnap_6800_cb (MMQcdmSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = user_data;
- QCDMResult *result;
+ QcdmResult *result;
GByteArray *nwsnap;
if (error)
goto done;
/* Parse the response */
- result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const char *) response->data, response->len, &info->error);
+ result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const char *) response->data, response->len, NULL);
if (!result) {
- g_clear_error (&info->error);
-
/* Try for MSM6500 */
nwsnap = g_byte_array_sized_new (25);
- nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6500, NULL);
+ nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6500);
g_assert (nwsnap->len);
mm_qcdm_serial_port_queue_command (port, nwsnap, 3, reg_nwsnap_6500_cb, info);
return;
@@ -282,7 +280,7 @@ query_registration_state (MMGenericCdma *cdma,
/* Try MSM6800 first since newer cards use that */
nwsnap = g_byte_array_sized_new (25);
- nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6800, NULL);
+ nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6800);
g_assert (nwsnap->len);
mm_qcdm_serial_port_queue_command (port, nwsnap, 3, reg_nwsnap_6800_cb, info);
}
diff --git a/plugins/mm-modem-novatel-gsm.c b/plugins/mm-modem-novatel-gsm.c
index 5d78db7..706664c 100644
--- a/plugins/mm-modem-novatel-gsm.c
+++ b/plugins/mm-modem-novatel-gsm.c
@@ -198,8 +198,6 @@ parse_nwrat_response (GString *response,
mode = atoi (str);
g_free (str);
- g_match_info_free (match_info);
-
if (mode < 0 || mode > 2) {
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Failed to parse mode/tech response");
@@ -219,6 +217,7 @@ parse_nwrat_response (GString *response,
success = TRUE;
out:
+ g_match_info_free (match_info);
g_regex_unref (r);
return success;
}
diff --git a/plugins/mm-modem-samsung-gsm.c b/plugins/mm-modem-samsung-gsm.c
index f2d339b..05cebe4 100755
--- a/plugins/mm-modem-samsung-gsm.c
+++ b/plugins/mm-modem-samsung-gsm.c
@@ -357,9 +357,9 @@ send_samsung_pinnum_done (MMAtSerialPort *port,
mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
- g_match_info_free (match_info);
-
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_serial_port_close (MM_SERIAL_PORT (port));
diff --git a/plugins/mm-modem-sierra-gsm.c b/plugins/mm-modem-sierra-gsm.c
index 551142e..1a9b735 100644
--- a/plugins/mm-modem-sierra-gsm.c
+++ b/plugins/mm-modem-sierra-gsm.c
@@ -25,12 +25,16 @@
#include "mm-modem-simple.h"
#include "mm-callback-info.h"
#include "mm-modem-helpers.h"
+#include "mm-log.h"
+#include "mm-modem-icera.h"
static void modem_init (MMModem *modem_class);
+static void modem_icera_init (MMModemIcera *icera_class);
static void modem_simple_init (MMModemSimple *class);
G_DEFINE_TYPE_EXTENDED (MMModemSierraGsm, mm_modem_sierra_gsm, MM_TYPE_GENERIC_GSM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init)
+ G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_ICERA, modem_icera_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init))
#define MM_MODEM_SIERRA_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_SIERRA_GSM, MMModemSierraGsmPrivate))
@@ -40,6 +44,8 @@ typedef struct {
gboolean has_net;
char *username;
char *password;
+ gboolean is_icera;
+ MMModemIceraPrivate *icera;
} MMModemSierraGsmPrivate;
MMModem *
@@ -49,17 +55,23 @@ mm_modem_sierra_gsm_new (const char *device,
guint32 vendor,
guint32 product)
{
+ MMModem *modem;
+
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
g_return_val_if_fail (plugin != NULL, NULL);
- return MM_MODEM (g_object_new (MM_TYPE_MODEM_SIERRA_GSM,
- MM_MODEM_MASTER_DEVICE, device,
- MM_MODEM_DRIVER, driver,
- MM_MODEM_PLUGIN, plugin,
- MM_MODEM_HW_VID, vendor,
- MM_MODEM_HW_PID, product,
- NULL));
+ modem = (MMModem *) g_object_new (MM_TYPE_MODEM_SIERRA_GSM,
+ MM_MODEM_MASTER_DEVICE, device,
+ MM_MODEM_DRIVER, driver,
+ MM_MODEM_PLUGIN, plugin,
+ MM_MODEM_HW_VID, vendor,
+ MM_MODEM_HW_PID, product,
+ NULL);
+ if (modem)
+ MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->icera = mm_modem_icera_init_private ();
+
+ return modem;
}
/*****************************************************************************/
@@ -72,7 +84,7 @@ get_allowed_mode_done (MMAtSerialPort *port,
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
GRegex *r = NULL;
- GMatchInfo *match_info;
+ GMatchInfo *match_info = NULL;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -127,6 +139,8 @@ get_allowed_mode_done (MMAtSerialPort *port,
}
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_callback_info_schedule (info);
@@ -137,9 +151,15 @@ get_allowed_mode (MMGenericGsm *gsm,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (gsm);
MMCallbackInfo *info;
MMAtSerialPort *primary;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (self)->is_icera) {
+ mm_modem_icera_get_allowed_mode (MM_MODEM_ICERA (self), callback, user_data);
+ return;
+ }
+
info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data);
/* Sierra secondary ports don't have full AT command interpreters */
@@ -179,11 +199,17 @@ set_allowed_mode (MMGenericGsm *gsm,
MMModemFn callback,
gpointer user_data)
{
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (gsm);
MMCallbackInfo *info;
MMAtSerialPort *primary;
char *command;
int idx = 0;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (self)->is_icera) {
+ mm_modem_icera_set_allowed_mode (MM_MODEM_ICERA (self), mode, callback, user_data);
+ return;
+ }
+
info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data);
/* Sierra secondary ports don't have full AT command interpreters */
@@ -251,9 +277,15 @@ get_access_technology (MMGenericGsm *modem,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (modem);
MMAtSerialPort *port;
MMCallbackInfo *info;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (self)->is_icera) {
+ mm_modem_icera_get_access_technology (MM_MODEM_ICERA (self), callback, user_data);
+ return;
+ }
+
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
port = mm_generic_gsm_get_best_at_port (modem, &info->error);
@@ -353,6 +385,28 @@ error:
/* Modem class override functions */
/*****************************************************************************/
+static void
+icera_check_cb (MMModem *modem,
+ guint32 result,
+ GError *error,
+ gpointer user_data)
+{
+ if (!error) {
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (user_data);
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
+
+ if (result) {
+ priv->is_icera = TRUE;
+ g_object_set (G_OBJECT (modem),
+ MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_STATIC,
+ NULL);
+
+ /* Turn on unsolicited network state messages */
+ mm_modem_icera_change_unsolicited_messages (MM_MODEM_ICERA (modem), TRUE);
+ }
+ }
+}
+
static gboolean
sierra_enabled (gpointer user_data)
{
@@ -365,6 +419,8 @@ sierra_enabled (gpointer user_data)
modem = MM_GENERIC_GSM (info->modem);
priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem);
priv->enable_wait_id = 0;
+ mm_modem_icera_is_icera (MM_MODEM_ICERA (modem), icera_check_cb, MM_MODEM_SIERRA_GSM (modem));
+
MM_GENERIC_GSM_CLASS (mm_modem_sierra_gsm_parent_class)->do_enable_power_up_done (modem, NULL, NULL, info);
}
return FALSE;
@@ -391,6 +447,64 @@ real_do_enable_power_up_done (MMGenericGsm *gsm,
priv->enable_wait_id = g_timeout_add_seconds (10, sierra_enabled, info);
}
+static void
+get_current_functionality_status_cb (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+ guint needed = FALSE;
+
+ /* If the modem has already been removed, return without
+ * scheduling callback */
+ if (mm_callback_info_check_modem_removed (info))
+ return;
+
+ /* On error, just assume we don't need the power-up command */
+ if (!error) {
+ const gchar *p;
+
+ p = mm_strip_tag (response->str, "+CFUN:");
+ if (p && *p == '1') {
+ /* If reported functionality status is '1', then we do not need to
+ * issue the power-up command. Otherwise, do it. */
+ mm_dbg ("Already in full functionality status, skipping power-up command");
+ } else {
+ needed = TRUE;
+ mm_warn ("Not in full functionality status, power-up command is needed.");
+ }
+ } else
+ mm_warn ("Failed checking if power-up command is needed: '%s'. "
+ "Will assume it isn't.",
+ error->message);
+
+ /* Set result and schedule */
+ mm_callback_info_set_result (info,
+ GUINT_TO_POINTER (needed),
+ NULL);
+ mm_callback_info_schedule (info);
+}
+
+static void
+do_enable_power_up_check_needed (MMGenericGsm *self,
+ MMModemUIntFn callback,
+ gpointer user_data)
+{
+ MMAtSerialPort *primary;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+
+ /* Get port */
+ primary = mm_generic_gsm_get_at_port (self, MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ /* Get current functionality status */
+ mm_dbg ("Getting current functionality status...");
+ mm_at_serial_port_queue_command (primary, "+CFUN?", 3, get_current_functionality_status_cb, info);
+}
+
static gboolean
grab_port (MMModem *modem,
const char *subsys,
@@ -422,6 +536,9 @@ grab_port (MMModem *modem,
regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL);
g_regex_unref (regex);
+
+ /* Add Icera-specific handlers */
+ mm_modem_icera_register_unsolicted_handlers (MM_MODEM_ICERA (gsm), MM_AT_SERIAL_PORT (port));
} else if (mm_port_get_subsys (port) == MM_PORT_SUBSYS_NET) {
MM_MODEM_SIERRA_GSM_GET_PRIVATE (gsm)->has_net = TRUE;
g_object_set (G_OBJECT (gsm), MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_DHCP, NULL);
@@ -554,6 +671,11 @@ do_connect (MMModem *modem,
MMCallbackInfo *info;
MMAtSerialPort *port;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->is_icera) {
+ mm_modem_icera_do_connect (MM_MODEM_ICERA (modem), number, callback, user_data);
+ return;
+ }
+
mm_modem_set_state (modem, MM_MODEM_STATE_CONNECTING, MM_MODEM_STATE_REASON_NONE);
info = mm_callback_info_new (modem, callback, user_data);
@@ -573,6 +695,21 @@ do_connect (MMModem *modem,
}
static void
+get_ip4_config (MMModem *modem,
+ MMModemIp4Fn callback,
+ gpointer user_data)
+{
+ MMModem *parent_iface;
+
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->is_icera) {
+ mm_modem_icera_get_ip4_config (MM_MODEM_ICERA (modem), callback, user_data);
+ } else {
+ parent_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (modem));
+ parent_iface->get_ip4_config (modem, callback, user_data);
+ }
+}
+
+static void
clear_user_pass (MMModemSierraGsm *self)
{
MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
@@ -589,9 +726,17 @@ do_disconnect (MMGenericGsm *gsm,
MMModemFn callback,
gpointer user_data)
{
- clear_user_pass (MM_MODEM_SIERRA_GSM (gsm));
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (gsm);
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
- if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (gsm)->has_net) {
+ if (priv->is_icera) {
+ mm_modem_icera_do_disconnect (gsm, cid, callback, user_data);
+ return;
+ }
+
+ clear_user_pass (self);
+
+ if (priv->has_net) {
MMAtSerialPort *primary;
char *command;
@@ -607,6 +752,68 @@ do_disconnect (MMGenericGsm *gsm,
MM_GENERIC_GSM_CLASS (mm_modem_sierra_gsm_parent_class)->do_disconnect (gsm, cid, callback, user_data);
}
+
+/*****************************************************************************/
+
+static void
+disable_unsolicited_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;
+
+ /* Ignore all errors */
+ mm_callback_info_schedule (info);
+}
+
+static void
+invoke_call_parent_disable_fn (MMCallbackInfo *info)
+{
+ /* Note: we won't call the parent disable if info->modem is no longer
+ * valid. The invoke is called always once the info gets scheduled, which
+ * may happen during removed modem detection. */
+ if (info->modem) {
+ MMModem *parent_modem_iface;
+
+ parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (info->modem));
+ parent_modem_iface->disable (info->modem, (MMModemFn)info->callback, info->user_data);
+ }
+}
+
+static void
+do_disable (MMModem *modem,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem);
+ MMAtSerialPort *primary;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (modem,
+ invoke_call_parent_disable_fn,
+ (GCallback)callback,
+ user_data);
+
+ primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ /* Turn off unsolicited responses */
+ if (priv->is_icera) {
+ mm_modem_icera_cleanup (MM_MODEM_ICERA (modem));
+ mm_modem_icera_change_unsolicited_messages (MM_MODEM_ICERA (modem), FALSE);
+ }
+
+ /* Random command to ensure unsolicited message disable completes */
+ mm_at_serial_port_queue_command (primary, "E0", 5, disable_unsolicited_done, info);
+}
+
/*****************************************************************************/
/* Simple Modem class override functions */
/*****************************************************************************/
@@ -640,9 +847,13 @@ simple_connect (MMModemSimple *simple,
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMModemSimple *parent_iface;
- clear_user_pass (MM_MODEM_SIERRA_GSM (simple));
- priv->username = simple_dup_string_property (properties, "username", &info->error);
- priv->password = simple_dup_string_property (properties, "password", &info->error);
+ if (priv->is_icera) {
+ mm_modem_icera_simple_connect (MM_MODEM_ICERA (simple), properties);
+ } else {
+ clear_user_pass (MM_MODEM_SIERRA_GSM (simple));
+ priv->username = simple_dup_string_property (properties, "username", &info->error);
+ priv->password = simple_dup_string_property (properties, "password", &info->error);
+ }
parent_iface = g_type_interface_peek_parent (MM_MODEM_SIMPLE_GET_INTERFACE (simple));
parent_iface->connect (MM_MODEM_SIMPLE (simple), properties, callback, info);
@@ -650,11 +861,27 @@ simple_connect (MMModemSimple *simple,
/*****************************************************************************/
+static MMModemIceraPrivate *
+get_icera_private (MMModemIcera *icera)
+{
+ return MM_MODEM_SIERRA_GSM_GET_PRIVATE (icera)->icera;
+}
+
+/*****************************************************************************/
+
static void
modem_init (MMModem *modem_class)
{
modem_class->grab_port = grab_port;
modem_class->connect = do_connect;
+ modem_class->disable = do_disable;
+ modem_class->get_ip4_config = get_ip4_config;
+}
+
+static void
+modem_icera_init (MMModemIcera *icera)
+{
+ icera->get_private = get_icera_private;
}
static void
@@ -671,12 +898,15 @@ mm_modem_sierra_gsm_init (MMModemSierraGsm *self)
static void
dispose (GObject *object)
{
- MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (object);
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (object);
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
if (priv->enable_wait_id)
g_source_remove (priv->enable_wait_id);
- clear_user_pass (MM_MODEM_SIERRA_GSM (object));
+ mm_modem_icera_dispose_private (MM_MODEM_ICERA (self));
+
+ clear_user_pass (self);
}
static void
@@ -689,6 +919,7 @@ mm_modem_sierra_gsm_class_init (MMModemSierraGsmClass *klass)
g_type_class_add_private (object_class, sizeof (MMModemSierraGsmPrivate));
object_class->dispose = dispose;
+ gsm_class->do_enable_power_up_check_needed = do_enable_power_up_check_needed;
gsm_class->do_enable_power_up_done = real_do_enable_power_up_done;
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;
diff --git a/plugins/mm-modem-wavecom-gsm.c b/plugins/mm-modem-wavecom-gsm.c
index c66637c..3bfcdbe 100644
--- a/plugins/mm-modem-wavecom-gsm.c
+++ b/plugins/mm-modem-wavecom-gsm.c
@@ -218,15 +218,20 @@ get_property (GObject *object,
{
switch (prop_id) {
case MM_GENERIC_GSM_PROP_POWER_UP_CMD:
- /* Wavecom doesn't like CFUN=1, it will reset the whole software stack,
- * including the USB connection and therefore connection would get
- * closed */
- g_value_set_string (value, "");
+ /* Try to go to full functionality mode without rebooting the system.
+ * Works well if we previously switched off the power with CFUN=4
+ */
+ g_value_set_string (value, "+CFUN=1,0");
break;
case MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD:
/* Wavecom doesn't have XOFF/XON flow control, so we enable RTS/CTS */
g_value_set_string (value, "+IFC=2,2");
break;
+ case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
+ /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and
+ * keeps access to the SIM */
+ g_value_set_string (value, "+CFUN=4");
+ break;
default:
break;
}
@@ -869,7 +874,7 @@ set_highest_ms_class_cb (MMAtSerialPort *port,
}
/* All done without errors! */
- mm_dbg ("[5/5] All done");
+ mm_dbg ("[4/4] All done");
enable_complete (MM_GENERIC_GSM (info->modem), NULL, info);
}
@@ -975,7 +980,7 @@ get_current_ms_class_cb (MMAtSerialPort *port,
}
/* Next, set highest mobile station class possible */
- mm_dbg ("[4/5] Ensuring highest MS class...");
+ mm_dbg ("[3/4] Ensuring highest MS class...");
set_highest_ms_class (port, info);
}
@@ -1039,19 +1044,18 @@ get_supported_ms_classes_cb (MMAtSerialPort *port,
}
/* Next, query for current MS class */
- mm_dbg ("[3/5] Getting current MS class...");
+ mm_dbg ("[2/4] Getting current MS class...");
mm_at_serial_port_queue_command (port, "+CGCLASS?", 3, get_current_ms_class_cb, info);
}
static void
-get_current_functionality_status_cb (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
+do_enable_power_up_done (MMGenericGsm *gsm,
+ GString *response,
+ GError *error,
+ MMCallbackInfo *info)
{
- MMCallbackInfo *info = user_data;
- const gchar *p;
- GError *inner_error;
+ MMAtSerialPort *port;
+ GError *inner_error = NULL;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -1059,57 +1063,79 @@ get_current_functionality_status_cb (MMAtSerialPort *port,
return;
if (error) {
- enable_complete (MM_GENERIC_GSM (info->modem), error, info);
+ enable_complete (gsm, error, info);
return;
}
- p = mm_strip_tag (response->str, "+CFUN:");
- if (!p || *p != '1') {
- /* Reported functionality status MUST be '1'. Otherwise, RF is probably
- * switched off. */
- inner_error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Unexpected functionality status: '%c'. ",
- p ? *p :' ');
- enable_complete (MM_GENERIC_GSM (info->modem), inner_error, info);
+ /* Get port */
+ port = mm_generic_gsm_get_best_at_port (gsm, &inner_error);
+ if (!port) {
+ enable_complete (gsm, inner_error, info);
g_error_free (inner_error);
+ return;
}
- /* Nex, query for supported MS classes */
- mm_dbg ("[2/5] Getting supported MS classes...");
+ mm_dbg ("[1/4] Getting supported MS classes...");
mm_at_serial_port_queue_command (port, "+CGCLASS=?", 3, get_supported_ms_classes_cb, info);
}
static void
-do_enable_power_up_done (MMGenericGsm *gsm,
- GString *response,
- GError *error,
- MMCallbackInfo *info)
+get_current_functionality_status_cb (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- MMAtSerialPort *port;
- GError *inner_error = NULL;
+ MMCallbackInfo *info = user_data;
+ guint needed = FALSE;
/* If the modem has already been removed, return without
* scheduling callback */
if (mm_callback_info_check_modem_removed (info))
return;
- if (error) {
- enable_complete (gsm, error, info);
- return;
- }
+ /* On error, just assume we don't need the power-up command */
+ if (!error) {
+ const gchar *p;
+
+ p = mm_strip_tag (response->str, "+CFUN:");
+ if (p && *p == '1') {
+ /* If reported functionality status is '1', then we do not need to
+ * issue the power-up command. Otherwise, do it. */
+ mm_dbg ("Already in full functionality status, skipping power-up command");
+ } else {
+ needed = TRUE;
+ mm_warn ("Not in full functionality status, power-up command is needed. "
+ "Note that it may reboot the modem.");
+ }
+ } else
+ mm_warn ("Failed checking if power-up command is needed: '%s'. "
+ "Will assume it isn't.",
+ error->message);
+
+ /* Set result and schedule */
+ mm_callback_info_set_result (info,
+ GUINT_TO_POINTER (needed),
+ NULL);
+ mm_callback_info_schedule (info);
+}
+
+static void
+do_enable_power_up_check_needed (MMGenericGsm *self,
+ MMModemUIntFn callback,
+ gpointer user_data)
+{
+ MMAtSerialPort *primary;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
/* Get port */
- port = mm_generic_gsm_get_best_at_port (gsm, &inner_error);
- if (!port) {
- enable_complete (gsm, inner_error, info);
- g_error_free (inner_error);
- return;
- }
+ primary = mm_generic_gsm_get_at_port (self, MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
- /* Next, get current functionality status */
- mm_dbg ("[1/5] Getting current functionality status...");
- mm_at_serial_port_queue_command (port, "+CFUN?", 3, get_current_functionality_status_cb, info);
+ /* Get current functionality status */
+ mm_dbg ("Getting current functionality status...");
+ mm_at_serial_port_queue_command (primary, "+CFUN?", 3, get_current_functionality_status_cb, info);
}
/*****************************************************************************/
@@ -1158,6 +1184,11 @@ mm_modem_wavecom_gsm_class_init (MMModemWavecomGsmClass *klass)
MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD,
MM_GENERIC_GSM_FLOW_CONTROL_CMD);
+ g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_POWER_DOWN_CMD,
+ MM_GENERIC_GSM_POWER_DOWN_CMD);
+
+ gsm_class->do_enable_power_up_check_needed = do_enable_power_up_check_needed;
gsm_class->do_enable_power_up_done = do_enable_power_up_done;
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;
diff --git a/plugins/mm-modem-x22x-gsm.c b/plugins/mm-modem-x22x-gsm.c
index 012733d..a31cd36 100644
--- a/plugins/mm-modem-x22x-gsm.c
+++ b/plugins/mm-modem-x22x-gsm.c
@@ -81,8 +81,6 @@ parse_syssel_response (GString *response,
mode = atoi (str);
g_free (str);
- g_match_info_free (match_info);
-
if (mode < 0 || mode > 2) {
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Failed to parse mode/tech response");
@@ -102,6 +100,7 @@ parse_syssel_response (GString *response,
success = TRUE;
out:
+ g_match_info_free (match_info);
g_regex_unref (r);
return success;
}
diff --git a/plugins/mm-modem-zte.c b/plugins/mm-modem-zte.c
index 6c9f395..88ef734 100644
--- a/plugins/mm-modem-zte.c
+++ b/plugins/mm-modem-zte.c
@@ -105,7 +105,7 @@ get_allowed_mode_done (MMAtSerialPort *port,
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
GRegex *r = NULL;
- GMatchInfo *match_info;
+ GMatchInfo *match_info = NULL;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -138,8 +138,6 @@ get_allowed_mode_done (MMAtSerialPort *port,
pref_acq = atoi (str);
g_free (str);
- g_match_info_free (match_info);
-
if (cm_mode < 0 || cm_mode > 2 || pref_acq < 0 || pref_acq > 2) {
info->error = g_error_new (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
@@ -164,6 +162,8 @@ get_allowed_mode_done (MMAtSerialPort *port,
}
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_callback_info_schedule (info);
diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c
index aef3c52..fe7ffa0 100644
--- a/plugins/mm-plugin-huawei.c
+++ b/plugins/mm-plugin-huawei.c
@@ -15,7 +15,6 @@
*/
#include <string.h>
-#include <stdlib.h>
#include <gmodule.h>
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
@@ -29,7 +28,6 @@
#include "mm-serial-parsers.h"
#include "mm-at-serial-port.h"
#include "mm-log.h"
-#include "mm-errors.h"
G_DEFINE_TYPE (MMPluginHuawei, mm_plugin_huawei, MM_TYPE_PLUGIN_BASE)
@@ -46,8 +44,6 @@ mm_plugin_create (void)
/*****************************************************************************/
-#define TAG_HUAWEI_PCUI_PORT "huawei-pcui-port"
-
#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
MM_PLUGIN_BASE_PORT_CAP_IS856 | \
@@ -74,59 +70,95 @@ probe_result (MMPluginBase *base,
mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
+#define TAG_SUPPORTS_INFO "huawei-supports-info"
+
+typedef struct {
+ MMAtSerialPort *serial;
+ guint id;
+ MMPortType ptype;
+ /* Whether or not there's already a detected modem that "owns" this port,
+ * in which case we'll claim it, but if no capabilities are detected it'll
+ * just be ignored.
+ */
+ gboolean parent_modem;
+} HuaweiSupportsInfo;
+
+static void
+huawei_supports_info_destroy (gpointer user_data)
+{
+ HuaweiSupportsInfo *info = user_data;
+
+ if (info->id)
+ g_source_remove (info->id);
+ if (info->serial)
+ g_object_unref (info->serial);
+ memset (info, 0, sizeof (HuaweiSupportsInfo));
+ g_free (info);
+}
+
static gboolean
-getportmode_response_cb (MMPluginBaseSupportsTask *task,
- GString *response,
- GError *error,
- guint32 tries,
- gboolean *out_stop,
- guint32 *out_level,
- gpointer user_data)
+probe_secondary_supported (gpointer user_data)
{
- /* If any error occurred that was not ERROR or COMMAND NOT SUPPORT then
- * retry the command.
- */
- if (error) {
- if (g_error_matches (error, MM_MOBILE_ERROR, MM_MOBILE_ERROR_UNKNOWN) == FALSE)
- return tries <= 4 ? TRUE : FALSE;
- } else {
- MMPlugin *plugin;
- char *p;
- int i = 0;
-
- /* Get the USB interface number of the PCUI port */
- p = strstr (response->str, "PCUI:");
- if (p)
- i = atoi (p + strlen ("PCUI:"));
-
- if (i) {
- /* Save they PCUI port number for later */
- plugin = mm_plugin_base_supports_task_get_plugin (task);
- g_assert (plugin);
- g_object_set_data (G_OBJECT (plugin), TAG_HUAWEI_PCUI_PORT, GINT_TO_POINTER (i));
- }
- }
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
+
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
- /* No error or if ^GETPORTMODE is not supported, assume success */
+ info->id = 0;
+ g_object_unref (info->serial);
+ info->serial = NULL;
+
+ /* Yay, supported, we got an unsolicited message */
+ info->ptype = MM_PORT_TYPE_SECONDARY;
+ mm_plugin_base_supports_task_complete (task, 10);
return FALSE;
}
+static void
+probe_secondary_handle_msg (MMAtSerialPort *port,
+ GMatchInfo *match_info,
+ gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
+
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ g_source_remove (info->id);
+ info->id = g_idle_add (probe_secondary_supported, task);
+}
+
static gboolean
-curc_response_cb (MMPluginBaseSupportsTask *task,
- GString *response,
- GError *error,
- guint32 tries,
- gboolean *out_stop,
- guint32 *out_level,
- gpointer user_data)
+probe_secondary_timeout (gpointer user_data)
{
- if (error)
- return tries <= 4 ? TRUE : FALSE;
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
+ guint level = 0;
+
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ info->id = 0;
+ g_object_unref (info->serial);
+ info->serial = NULL;
+
+ /* Supported, but ignored if this port's parent device is already a modem */
+ if (info->parent_modem) {
+ info->ptype = MM_PORT_TYPE_IGNORED;
+ level = 10;
+ }
- /* No error, assume success */
+ mm_plugin_base_supports_task_complete (task, level);
return FALSE;
}
+static void
+add_regex (MMAtSerialPort *port, const char *match, gpointer user_data)
+{
+ GRegex *regex;
+
+ regex = g_regex_new (match, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_at_serial_port_add_unsolicited_msg_handler (port, regex, probe_secondary_handle_msg, user_data, NULL);
+ g_regex_unref (regex);
+}
+
static MMPluginSupportsResult
supports_port (MMPluginBase *base,
MMModem *existing,
@@ -134,9 +166,10 @@ supports_port (MMPluginBase *base,
{
GUdevDevice *port;
guint32 cached = 0, level;
- const char *subsys, *name;
+ const char *subsys, *name, *driver;
int usbif;
guint16 vendor = 0, product = 0;
+ guint32 existing_type = MM_MODEM_TYPE_UNKNOWN;
/* Can't do anything with non-serial ports */
port = mm_plugin_base_supports_task_get_port (task);
@@ -152,52 +185,81 @@ supports_port (MMPluginBase *base,
if (vendor != 0x12d1)
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ /* The Gobi driver should claim Huawei Gobi modems */
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (g_strcmp0 (driver, "qcserial") == 0)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
usbif = g_udev_device_get_property_as_int (port, "ID_USB_INTERFACE_NUM");
if (usbif < 0)
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- /* The primary port (called the "modem" port in the Windows drivers) is
- * always USB interface 0, and we need to detect that interface first for
- * two reasons: (1) to disable unsolicited messages on other ports that
- * may fill up the buffer and crash the device, and (2) to attempt to get
- * the port layout for hints about what the secondary port is (called the
- * "pcui" port in Windows). Thus we probe USB interface 0 first and defer
- * probing other interfaces until we've got if0, at which point we allow
- * the other ports to be probed too.
+ /* The secondary ports don't necessarily respond correctly to probing, so
+ * we need to use the first port that does respond to probing to create the
+ * right type of mode (GSM or CDMA), and then re-check the other interfaces.
*/
if (!existing && usbif != 0)
return MM_PLUGIN_SUPPORTS_PORT_DEFER;
- if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
- level = get_level_for_capabilities (cached);
- if (level) {
- mm_plugin_base_supports_task_complete (task, level);
+ /* CDMA devices don't have problems with the secondary ports, so after
+ * ensuring we have a device by probing the first port, probe the secondary
+ * ports on CDMA devices too.
+ */
+ if (existing)
+ g_object_get (G_OBJECT (existing), MM_MODEM_TYPE, &existing_type, NULL);
+
+ if (usbif == 0 || (existing_type == MM_MODEM_TYPE_CDMA)) {
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
+
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, 100000, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ } else {
+ HuaweiSupportsInfo *info;
+ GError *error = NULL;
+
+ /* Listen for Huawei-specific unsolicited messages */
+ info = g_malloc0 (sizeof (HuaweiSupportsInfo));
+ info->parent_modem = !!existing;
+
+ info->serial = mm_at_serial_port_new (name, MM_PORT_TYPE_PRIMARY);
+ g_object_set (G_OBJECT (info->serial), MM_PORT_CARRIER_DETECT, FALSE, NULL);
+
+ mm_at_serial_port_set_response_parser (info->serial,
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
+
+ add_regex (info->serial, "\\r\\n\\^RSSI:(\\d+)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^BOOT:.+\\r\\n", task);
+ add_regex (info->serial, "\\r\\r\\^BOOT:.+\\r\\r", task);
+
+ info->id = g_timeout_add_seconds (7, probe_secondary_timeout, task);
+
+ if (!mm_serial_port_open (MM_SERIAL_PORT (info->serial), &error)) {
+ mm_warn ("(Huawei) %s: couldn't open serial port: (%d) %s",
+ name,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ huawei_supports_info_destroy (info);
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- }
- /* Turn off unsolicited messages on secondary ports until needed,
- * and try to get a port map from the modem. The response will
- * get handled in custom_init_response().
- */
- if (usbif == 0) {
- mm_plugin_base_supports_task_add_custom_init_command (task,
- "AT^CURC=0",
- 3, /* delay */
- curc_response_cb,
- NULL);
-
- mm_plugin_base_supports_task_add_custom_init_command (task,
- "AT^GETPORTMODE",
- 3, /* delay */
- getportmode_response_cb,
- NULL);
- }
+ g_object_set_data_full (G_OBJECT (task), TAG_SUPPORTS_INFO,
+ info, huawei_supports_info_destroy);
- /* Kick off a probe */
- if (mm_plugin_base_probe_port (base, task, 100000, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
@@ -257,21 +319,12 @@ grab_port (MMPluginBase *base,
}
}
} else {
+ HuaweiSupportsInfo *info;
MMPortType ptype = MM_PORT_TYPE_UNKNOWN;
- int pcui_usbif, port_usbif;
-
- /* Any additional AT ports can be secondary ports, but we want to ensure
- * that the "pcui" port found from ^GETPORTMODE above is always set as
- * a secondary port too.
- */
-
- port_usbif = g_udev_device_get_property_as_int (port, "ID_USB_INTERFACE_NUM");
- pcui_usbif = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (base), TAG_HUAWEI_PCUI_PORT));
- if ( (port_usbif == pcui_usbif)
- || (caps & MM_PLUGIN_BASE_PORT_CAP_GSM)
- || (caps & CAP_CDMA))
- ptype = MM_PORT_TYPE_SECONDARY;
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ if (info)
+ ptype = info->ptype;
else if (caps & MM_PLUGIN_BASE_PORT_CAP_QCDM)
ptype = MM_PORT_TYPE_QCDM;
diff --git a/plugins/mm-plugin-longcheer.c b/plugins/mm-plugin-longcheer.c
index 5f773a3..89a6138 100644
--- a/plugins/mm-plugin-longcheer.c
+++ b/plugins/mm-plugin-longcheer.c
@@ -72,12 +72,13 @@ custom_init_response_cb (MMPluginBaseSupportsTask *task,
guint32 *out_level,
gpointer user_data)
{
- const char *p = response->str;
+ const char *p;
if (error)
return tries <= 4 ? TRUE : FALSE;
/* Note the lack of a ':' on the GMR; the X200 doesn't send one */
+ g_assert (response);
p = mm_strip_tag (response->str, "AT+GMR");
if (*p == 'L') {
/* X200 modems have a GMR firmware revision that starts with 'L', and
diff --git a/plugins/mm-plugin-nokia.c b/plugins/mm-plugin-nokia.c
index 28e9022..de05c2d 100644
--- a/plugins/mm-plugin-nokia.c
+++ b/plugins/mm-plugin-nokia.c
@@ -59,6 +59,22 @@ probe_result (MMPluginBase *base,
mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
+static gboolean
+custom_init_response_cb (MMPluginBaseSupportsTask *task,
+ GString *response,
+ GError *error,
+ guint32 tries,
+ gboolean *out_stop,
+ guint32 *out_level,
+ gpointer user_data)
+{
+ if (error)
+ return tries <= 4 ? TRUE : FALSE;
+
+ /* No error, assume success */
+ return FALSE;
+}
+
static MMPluginSupportsResult
supports_port (MMPluginBase *base,
MMModem *existing,
@@ -92,6 +108,12 @@ supports_port (MMPluginBase *base,
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
+ mm_plugin_base_supports_task_add_custom_init_command (task,
+ "ATE1 E0",
+ 3,
+ custom_init_response_cb,
+ NULL);
+
/* Otherwise kick off a probe */
if (mm_plugin_base_probe_port (base, task, 100000, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
@@ -110,6 +132,7 @@ grab_port (MMPluginBase *base,
const char *name, *subsys, *devfile, *sysfs_path;
guint32 caps;
guint16 vendor = 0, product = 0;
+ MMPortType ptype = MM_PORT_TYPE_UNKNOWN;
port = mm_plugin_base_supports_task_get_port (task);
g_assert (port);
@@ -128,6 +151,12 @@ grab_port (MMPluginBase *base,
return NULL;
}
+ /* Look for port type hints */
+ if (g_udev_device_get_property_as_boolean (port, "ID_MM_NOKIA_PORT_TYPE_MODEM"))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (g_udev_device_get_property_as_boolean (port, "ID_MM_NOKIA_PORT_TYPE_AUX"))
+ ptype = MM_PORT_TYPE_SECONDARY;
+
caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
sysfs_path = mm_plugin_base_supports_task_get_physdev_path (task);
if (!existing) {
@@ -148,14 +177,14 @@ grab_port (MMPluginBase *base,
}
if (modem) {
- if (!mm_modem_grab_port (modem, subsys, name, MM_PORT_TYPE_UNKNOWN, NULL, error)) {
+ if (!mm_modem_grab_port (modem, subsys, name, ptype, NULL, error)) {
g_object_unref (modem);
return NULL;
}
}
} else if (get_level_for_capabilities (caps)) {
modem = existing;
- if (!mm_modem_grab_port (modem, subsys, name, MM_PORT_TYPE_UNKNOWN, NULL, error))
+ if (!mm_modem_grab_port (modem, subsys, name, ptype, NULL, error))
return NULL;
}
diff --git a/plugins/mm-plugin-x22x.c b/plugins/mm-plugin-x22x.c
index 3be6731..a76a919 100644
--- a/plugins/mm-plugin-x22x.c
+++ b/plugins/mm-plugin-x22x.c
@@ -70,12 +70,13 @@ custom_init_response_cb (MMPluginBaseSupportsTask *task,
guint32 *out_level,
gpointer user_data)
{
- const char *p = response->str;
+ const char *p;
if (error)
return tries <= 4 ? TRUE : FALSE;
/* Note the lack of a ':' on the GMR; the X200 doesn't send one */
+ g_assert (response);
p = mm_strip_tag (response->str, "AT+GMR");
if (*p != 'L') {
/* X200 modems have a GMR firmware revision that starts with 'L', and