aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--introspection/Makefile.am26
-rw-r--r--introspection/org.freedesktop.ModemManager.Modem.Cdma.xml2
-rw-r--r--introspection/org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml6
-rw-r--r--introspection/org.freedesktop.ModemManager.Modem.Gsm.xml3
-rw-r--r--introspection/org.freedesktop.ModemManager.Modem.xml13
-rw-r--r--libqcdm/src/commands.c101
-rw-r--r--libqcdm/src/commands.h33
-rw-r--r--libqcdm/src/nv-items.h29
-rw-r--r--libqcdm/tests/test-qcdm-com.c59
-rw-r--r--libqcdm/tests/test-qcdm-com.h2
-rw-r--r--libqcdm/tests/test-qcdm.c1
-rw-r--r--plugins/77-mm-zte-port-types.rules15
-rw-r--r--plugins/Makefile.am22
-rw-r--r--plugins/mm-modem-anydata-cdma.c28
-rw-r--r--plugins/mm-modem-huawei-cdma.c7
-rw-r--r--plugins/mm-modem-huawei-gsm.c85
-rw-r--r--plugins/mm-modem-icera.c794
-rw-r--r--plugins/mm-modem-icera.h89
-rw-r--r--plugins/mm-modem-mbm.c36
-rw-r--r--plugins/mm-modem-zte.c200
-rw-r--r--plugins/mm-plugin-generic.c9
-rw-r--r--plugins/mm-plugin-huawei.c9
-rw-r--r--plugins/mm-plugin-mbm.c2
-rw-r--r--plugins/mm-plugin-zte.c21
-rw-r--r--src/77-mm-usb-device-blacklist.rules6
-rw-r--r--src/Makefile.am4
-rw-r--r--src/main.c121
-rw-r--r--src/mm-at-serial-port.c10
-rw-r--r--src/mm-generic-cdma.c44
-rw-r--r--src/mm-generic-gsm.c260
-rw-r--r--src/mm-log.c227
-rw-r--r--src/mm-log.h61
-rw-r--r--src/mm-manager.c86
-rw-r--r--src/mm-modem-base.c63
-rw-r--r--src/mm-modem-cdma.c9
-rw-r--r--src/mm-modem-cdma.h8
-rw-r--r--src/mm-modem-gsm-network.c2
-rw-r--r--src/mm-modem-gsm-ussd.c77
-rw-r--r--src/mm-modem-gsm-ussd.h10
-rw-r--r--src/mm-modem-gsm.h3
-rw-r--r--src/mm-modem-helpers.c44
-rw-r--r--src/mm-modem-helpers.h3
-rw-r--r--src/mm-modem.c73
-rw-r--r--src/mm-modem.h8
-rw-r--r--src/mm-options.c55
-rw-r--r--src/mm-options.h23
-rw-r--r--src/mm-plugin-base.c7
-rw-r--r--src/mm-port.c30
-rw-r--r--src/mm-port.h2
-rw-r--r--src/mm-properties-changed-signal.c9
-rw-r--r--src/mm-qcdm-serial-port.c10
-rw-r--r--src/mm-serial-parsers.c5
-rw-r--r--src/mm-serial-port.c50
-rw-r--r--src/tests/test-modem-helpers.c26
-rw-r--r--src/tests/test-qcdm-serial-port.c11
-rwxr-xr-x[-rw-r--r--]test/ussd.py21
57 files changed, 2432 insertions, 529 deletions
diff --git a/Makefile.am b/Makefile.am
index 1c65967e..4132bc92 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -80,6 +80,7 @@ DISTCLEANFILES = \
EXTRA_DIST = \
doc-generator.xsl \
+ header-generator.xsl \
$(dbusactivation_in_files) \
$(INTLTOOL_FILES) \
$(dbusservice_file_polkit) \
diff --git a/introspection/Makefile.am b/introspection/Makefile.am
index 5c2a5ebb..3c7a380e 100644
--- a/introspection/Makefile.am
+++ b/introspection/Makefile.am
@@ -1,19 +1,19 @@
EXTRA_DIST = \
all.xml \
- mm-manager.xml \
+ org.freedesktop.ModemManager.xml \
mm-mobile-error.xml \
- mm-modem.xml \
- mm-modem-cdma.xml \
+ org.freedesktop.ModemManager.Modem.xml \
+ org.freedesktop.ModemManager.Modem.Cdma.xml \
mm-modem-connect-error.xml \
mm-modem-error.xml \
- mm-modem-gsm.xml \
- mm-modem-gsm-card.xml \
- mm-modem-gsm-contacts.xml \
- mm-modem-gsm-hso.xml \
- mm-modem-gsm-network.xml \
- mm-modem-gsm-sms.xml \
- mm-modem-simple.xml \
+ org.freedesktop.ModemManager.Modem.Gsm.xml \
+ org.freedesktop.ModemManager.Modem.Gsm.Card.xml \
+ org.freedesktop.ModemManager.Modem.Gsm.Contacts.xml \
+ org.freedesktop.ModemManager.Modem.Gsm.Hso.xml \
+ org.freedesktop.ModemManager.Modem.Gsm.Network.xml \
+ org.freedesktop.ModemManager.Modem.Gsm.SMS.xml \
+ org.freedesktop.ModemManager.Modem.Simple.xml \
mm-serial-error.xml \
- mm-modem-location.xml \
- mm-modem-gsm-ussd.xml \
- mm-properties-changed.xml
+ org.freedesktop.ModemManager.Modem.Location.xml \
+ org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml \
+ org.freedesktop.DBus.Properties.xml
diff --git a/introspection/org.freedesktop.ModemManager.Modem.Cdma.xml b/introspection/org.freedesktop.ModemManager.Modem.Cdma.xml
index 3e4c98b7..d80d9b9b 100644
--- a/introspection/org.freedesktop.ModemManager.Modem.Cdma.xml
+++ b/introspection/org.freedesktop.ModemManager.Modem.Cdma.xml
@@ -120,7 +120,7 @@
</arg>
</method>
- <property name="MEID" type="s" access="read">
+ <property name="Meid" type="s" access="read">
<tp:docstring>
The modem's Mobile Equipment Identifier.
</tp:docstring>
diff --git a/introspection/org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml b/introspection/org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml
index ae6884f0..8eef91d2 100644
--- a/introspection/org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml
+++ b/introspection/org.freedesktop.ModemManager.Modem.Gsm.Ussd.xml
@@ -38,6 +38,12 @@
request for further input.
</tp:docstring>
</arg>
+ <arg name="reply" type="s" direction="out">
+ <tp:docstring>
+ The network reply to this response to the network-initiated USSD
+ command. The reply may require further responses.
+ </tp:docstring>
+ </arg>
</method>
<method name="Cancel">
diff --git a/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml b/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml
index ea23adcf..78da9a44 100644
--- a/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml
+++ b/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml
@@ -157,6 +157,9 @@
<tp:enumvalue suffix="HSPA" value="8">
<tp:docstring>HSPA (ETSI 27.007: "UTRAN w/HSDPA and HSUPA")</tp:docstring>
</tp:enumvalue>
+ <tp:enumvalue suffix="HSPA_PLUS" value="9">
+ <tp:docstring>HSPA+ (ETSI 27.007: "UTRAN w/HSPA+")</tp:docstring>
+ </tp:enumvalue>
</tp:enum>
</interface>
diff --git a/introspection/org.freedesktop.ModemManager.Modem.xml b/introspection/org.freedesktop.ModemManager.Modem.xml
index e1a07293..d5da9525 100644
--- a/introspection/org.freedesktop.ModemManager.Modem.xml
+++ b/introspection/org.freedesktop.ModemManager.Modem.xml
@@ -63,9 +63,20 @@
</arg>
</method>
+ <method name="Reset">
+ <tp:docstring>
+ Clear non-persistent configuration and state, and return the device to
+ a newly-powered-on state. This command may power-cycle the device.
+ </tp:docstring>
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_reset"/>
+ </method>
+
<method name="FactoryReset">
<tp:docstring>
- Reset the modem to as close to factory state as possible.
+ Clear the modem's configuration (including persistent configuration and
+ state), and return the device to a factory-default state. This command
+ may or may not power-cycle the device.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_factory_reset"/>
diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c
index 47b517de..ab61ee51 100644
--- a/libqcdm/src/commands.c
+++ b/libqcdm/src/commands.c
@@ -873,6 +873,107 @@ qcdm_cmd_nv_set_mode_pref_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
+static gboolean
+hdr_rev_pref_validate (guint8 dm)
+{
+ if ( dm == DIAG_NV_HDR_REV_PREF_0
+ || dm == DIAG_NV_HDR_REV_PREF_A
+ || dm == DIAG_NV_HDR_REV_PREF_EHRPD)
+ return TRUE;
+ return FALSE;
+}
+
+gsize
+qcdm_cmd_nv_get_hdr_rev_pref_new (char *buf, gsize len, GError **error)
+{
+ char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
+ DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
+
+ g_return_val_if_fail (buf != NULL, 0);
+ g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_NV_READ;
+ cmd->nv_item = GUINT16_TO_LE (DIAG_NV_HDR_REV_PREF);
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QCDMResult *
+qcdm_cmd_nv_get_hdr_rev_pref_result (const char *buf, gsize len, GError **error)
+{
+ QCDMResult *result = NULL;
+ DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
+ DMNVItemHdrRevPref *rev;
+
+ g_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), error))
+ return NULL;
+
+ if (!check_nv_cmd (rsp, DIAG_NV_HDR_REV_PREF, error))
+ return NULL;
+
+ rev = (DMNVItemHdrRevPref *) &rsp->data[0];
+
+ if (!hdr_rev_pref_validate (rev->rev_pref)) {
+ g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
+ "Unknown HDR revision preference 0x%X",
+ rev->rev_pref);
+ return NULL;
+ }
+
+ result = qcdm_result_new ();
+ qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF, rev->rev_pref);
+
+ return result;
+}
+
+gsize
+qcdm_cmd_nv_set_hdr_rev_pref_new (char *buf,
+ gsize len,
+ guint8 rev_pref,
+ GError **error)
+{
+ char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
+ DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
+ DMNVItemHdrRevPref *req;
+
+ g_return_val_if_fail (buf != NULL, 0);
+ g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ if (!hdr_rev_pref_validate (rev_pref)) {
+ g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
+ "Invalid HDR revision preference %d", rev_pref);
+ return 0;
+ }
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_NV_WRITE;
+ cmd->nv_item = GUINT16_TO_LE (DIAG_NV_HDR_REV_PREF);
+
+ req = (DMNVItemHdrRevPref *) &cmd->data[0];
+ req->rev_pref = rev_pref;
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QCDMResult *
+qcdm_cmd_nv_set_hdr_rev_pref_result (const char *buf, gsize len, GError **error)
+{
+ g_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), error))
+ return NULL;
+
+ if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_HDR_REV_PREF, error))
+ return NULL;
+
+ return qcdm_result_new ();
+}
+
+/**********************************************************************/
+
gsize
qcdm_cmd_cm_subsys_state_info_new (char *buf, gsize len, GError **error)
{
diff --git a/libqcdm/src/commands.h b/libqcdm/src/commands.h
index 50a6f49a..fe582a68 100644
--- a/libqcdm/src/commands.h
+++ b/libqcdm/src/commands.h
@@ -300,6 +300,34 @@ QCDMResult *qcdm_cmd_nv_set_mode_pref_result (const char *buf,
/**********************************************************************/
+/* Values for QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF */
+enum {
+ QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_0 = 0x00,
+ QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_A = 0x01,
+ QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_EHRPD = 0x04,
+};
+
+#define QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF "rev-pref"
+
+gsize qcdm_cmd_nv_get_hdr_rev_pref_new (char *buf,
+ gsize len,
+ GError **error);
+
+QCDMResult *qcdm_cmd_nv_get_hdr_rev_pref_result (const char *buf,
+ gsize len,
+ GError **error);
+
+gsize qcdm_cmd_nv_set_hdr_rev_pref_new (char *buf,
+ gsize len,
+ guint8 rev_pref,
+ GError **error);
+
+QCDMResult *qcdm_cmd_nv_set_hdr_rev_pref_result (const char *buf,
+ gsize len,
+ GError **error);
+
+/**********************************************************************/
+
/* Values for QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE */
enum {
QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE = 5
@@ -313,7 +341,10 @@ enum {
QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GSM = 3,
QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_HDR = 4,
QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA = 5,
- QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GPS = 6
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GPS = 6,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GW = 7, /* GSM & WCDMA */
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WLAN = 8,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_LTE = 9,
};
/* Values for QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF */
diff --git a/libqcdm/src/nv-items.h b/libqcdm/src/nv-items.h
index a0ca10a6..8240866a 100644
--- a/libqcdm/src/nv-items.h
+++ b/libqcdm/src/nv-items.h
@@ -19,17 +19,21 @@
#define LIBQCDM_NV_ITEMS_H
enum {
- DIAG_NV_MODE_PREF = 10, /* Mode preference: 1x, HDR, auto */
- DIAG_NV_DIR_NUMBER = 178, /* Mobile Directory Number (MDN) */
- DIAG_NV_ROAM_PREF = 442, /* Roaming preference */
+ DIAG_NV_MODE_PREF = 10, /* Mode preference: 1x, HDR, auto */
+ DIAG_NV_DIR_NUMBER = 178, /* Mobile Directory Number (MDN) */
+ DIAG_NV_ROAM_PREF = 442, /* Roaming preference */
+ DIAG_NV_HDR_REV_PREF = 4964, /* HDR mode preference(?): rev0, revA, eHRPD */
};
/* Mode preference values */
enum {
- DIAG_NV_MODE_PREF_AUTO = 0x04,
- DIAG_NV_MODE_PREF_1X_ONLY = 0x09,
- DIAG_NV_MODE_PREF_HDR_ONLY = 0x0A,
+ DIAG_NV_MODE_PREF_AUTO = 0x04,
+ DIAG_NV_MODE_PREF_1X_ONLY = 0x09,
+ DIAG_NV_MODE_PREF_HDR_ONLY = 0x0A,
+ DIAG_NV_MODE_PREF_1X_HDR_ONLY = 0x0D,
+ DIAG_NV_MODE_PREF_LTE_ONLY = 0x1E,
+ DIAG_NV_MODE_PREF_1X_HDR_LTE_ONLY = 0x24,
};
/* DIAG_NV_MODE_PREF */
@@ -60,5 +64,18 @@ struct DMNVItemRoamPref {
} __attribute__ ((packed));
typedef struct DMNVItemRoamPref DMNVItemRoamPref;
+/* HDR Revision preference values (?) */
+enum {
+ DIAG_NV_HDR_REV_PREF_0 = 0x00,
+ DIAG_NV_HDR_REV_PREF_A = 0x01,
+ DIAG_NV_HDR_REV_PREF_EHRPD = 0x04,
+};
+
+/* DIAG_NV_HDR_REV_PREF */
+struct DMNVItemHdrRevPref {
+ guint8 rev_pref;
+} __attribute__ ((packed));
+typedef struct DMNVItemHdrRevPref DMNVItemHdrRevPref;
+
#endif /* LIBQCDM_NV_ITEMS_H */
diff --git a/libqcdm/tests/test-qcdm-com.c b/libqcdm/tests/test-qcdm-com.c
index 8e6113bd..b95c7d9b 100644
--- a/libqcdm/tests/test-qcdm-com.c
+++ b/libqcdm/tests/test-qcdm-com.c
@@ -575,6 +575,62 @@ test_com_read_mode_pref (void *f, void *data)
}
void
+test_com_read_hdr_rev_pref (void *f, void *data)
+{
+ TestComData *d = data;
+ gboolean success;
+ GError *error = NULL;
+ char buf[512];
+ guint8 pref;
+ const char *msg;
+ gint len;
+ QCDMResult *result;
+ gsize reply_len;
+
+ len = qcdm_cmd_nv_get_hdr_rev_pref_new (buf, sizeof (buf), NULL);
+ g_assert (len > 0);
+
+ /* Send the command */
+ success = send_command (d, buf, len);
+ g_assert (success);
+
+ /* Get a response */
+ reply_len = wait_reply (d, buf, sizeof (buf));
+
+ /* Parse the response into a result structure */
+ result = qcdm_cmd_nv_get_hdr_rev_pref_result (buf, reply_len, &error);
+ if (!result) {
+ g_assert (error);
+ g_assert (error->domain == QCDM_COMMAND_ERROR);
+ g_assert (error->code == QCDM_COMMAND_NVCMD_FAILED || error->code == QCDM_COMMAND_BAD_PARAMETER);
+ return;
+ }
+
+ g_print ("\n");
+
+ success = qcdm_result_get_uint8 (result, QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF, &pref);
+ g_assert (success);
+
+ switch (pref) {
+ case QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_0:
+ msg = "rev0";
+ break;
+ case QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_A:
+ msg = "revA";
+ break;
+ case QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_EHRPD:
+ msg = "eHRPD";
+ break;
+ default:
+ msg = "unknown";
+ break;
+ }
+ g_message ("%s: HDR rev preference: 0x%02X (%s)", __func__, pref, msg);
+
+ qcdm_result_unref (result);
+}
+
+void
test_com_status (void *f, void *data)
{
TestComData *d = data;
@@ -906,6 +962,9 @@ test_com_cm_subsys_state_info (void *f, void *data)
case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA:
detail = "WCDMA";
break;
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_LTE:
+ detail = "LTE";
+ break;
default:
detail = "unknown";
break;
diff --git a/libqcdm/tests/test-qcdm-com.h b/libqcdm/tests/test-qcdm-com.h
index 6b1f4ba7..76075e54 100644
--- a/libqcdm/tests/test-qcdm-com.h
+++ b/libqcdm/tests/test-qcdm-com.h
@@ -33,6 +33,8 @@ void test_com_read_roam_pref (void *f, void *data);
void test_com_read_mode_pref (void *f, void *data);
+void test_com_read_hdr_rev_pref (void *f, void *data);
+
void test_com_status (void *f, void *data);
void test_com_sw_version (void *f, void *data);
diff --git a/libqcdm/tests/test-qcdm.c b/libqcdm/tests/test-qcdm.c
index 5867bcb9..946fb673 100644
--- a/libqcdm/tests/test-qcdm.c
+++ b/libqcdm/tests/test-qcdm.c
@@ -102,6 +102,7 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_com_mdn, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_read_roam_pref, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_read_mode_pref, data->com_data));
+ g_test_suite_add (suite, TESTCASE (test_com_read_hdr_rev_pref, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_status, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_sw_version, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_status_snapshot, data->com_data));
diff --git a/plugins/77-mm-zte-port-types.rules b/plugins/77-mm-zte-port-types.rules
index bc6f05a9..072154ce 100644
--- a/plugins/77-mm-zte-port-types.rules
+++ b/plugins/77-mm-zte-port-types.rules
@@ -78,6 +78,9 @@ ATTRS{idProduct}=="0033", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}=
ATTRS{idProduct}=="0037", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0037", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+ATTRS{idProduct}=="0039", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
+ATTRS{idProduct}=="0039", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+
ATTRS{idProduct}=="0042", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0042", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
@@ -93,9 +96,15 @@ ATTRS{idProduct}=="0049", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_ZTE_PORT_TYPE_AUX}=
ATTRS{idProduct}=="0052", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0052", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+ATTRS{idProduct}=="0054", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
+ATTRS{idProduct}=="0054", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+
ATTRS{idProduct}=="0055", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0055", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+ATTRS{idProduct}=="0057", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
+ATTRS{idProduct}=="0057", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+
ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0061", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
@@ -108,9 +117,15 @@ ATTRS{idProduct}=="0064", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_ZTE_PORT_TYPE_AUX}=
ATTRS{idProduct}=="0066", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0066", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+ATTRS{idProduct}=="0082", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
+ATTRS{idProduct}=="0082", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+
ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0104", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+ATTRS{idProduct}=="0108", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
+ATTRS{idProduct}=="0108", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
+
ATTRS{idProduct}=="0113", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0113", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 9f85d54f..dd58b943 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,3 +1,24 @@
+
+##########################
+# Icera-specific support #
+##########################
+
+noinst_LTLIBRARIES = libicera-utils.la
+
+libicera_utils_la_SOURCES = \
+ mm-modem-icera.c \
+ mm-modem-icera.h
+
+libicera_utils_la_CPPFLAGS = \
+ $(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
+ -I$(top_srcdir)/src
+
+libicera_utils_la_LIBADD = \
+ $(GUDEV_LDFLAGS)
+
+########################################
+
pkglib_LTLIBRARIES = \
libmm-plugin-generic.la \
libmm-plugin-moto-c.la \
@@ -220,6 +241,7 @@ libmm_plugin_zte_la_CPPFLAGS = \
libmm_plugin_zte_la_LDFLAGS = \
$(GUDEV_LDFLAGS) \
+ $(builddir)/libicera-utils.la \
-module \
-avoid-version
diff --git a/plugins/mm-modem-anydata-cdma.c b/plugins/mm-modem-anydata-cdma.c
index 3bf15ed8..0e7e65c5 100644
--- a/plugins/mm-modem-anydata-cdma.c
+++ b/plugins/mm-modem-anydata-cdma.c
@@ -28,6 +28,7 @@
#include "mm-callback-info.h"
#include "mm-serial-port.h"
#include "mm-serial-parsers.h"
+#include "mm-log.h"
static void modem_init (MMModem *modem_class);
@@ -140,7 +141,7 @@ evdo_state_done (MMAtSerialPort *port,
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
if (!r) {
/* Parse error; warn about it and assume EVDO is not available */
- g_warning ("AnyDATA(%s): *HSTATE parse regex creation failed.", __func__);
+ mm_warn ("ANYDATA: *HSTATE parse regex creation failed.");
goto done;
}
@@ -167,7 +168,7 @@ evdo_state_done (MMAtSerialPort *port,
reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED;
break;
default:
- g_message ("ANYDATA: unknown *STATE (%d); assuming no service.", val);
+ mm_warn ("ANYDATA: unknown *STATE (%d); assuming no service.", val);
/* fall through */
case 0: /* NO SERVICE */
case 1: /* ACQUISITION */
@@ -206,7 +207,7 @@ state_done (MMAtSerialPort *port,
r = g_regex_new ("\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*([^,\\)]*)\\s*,.*",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
if (!r) {
- g_warning ("AnyDATA(%s): *STATE parse regex creation failed.", __func__);
+ mm_warn ("ANYDATA: *STATE parse regex creation failed.");
mm_callback_info_schedule (info);
return;
}
@@ -235,7 +236,7 @@ state_done (MMAtSerialPort *port,
reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED;
break;
default:
- g_warning ("ANYDATA: unknown *STATE (%d); assuming no service.", val);
+ mm_warn ("ANYDATA: unknown *STATE (%d); assuming no service.", val);
/* fall through */
case 0: /* NO SERVICE */
break;
@@ -272,6 +273,24 @@ query_registration_state (MMGenericCdma *cdma,
/*****************************************************************************/
+static void
+reset (MMModem *modem,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMAtSerialPort *port;
+
+ info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
+
+ /* Ensure we have a usable port to use for the command */
+ port = mm_generic_cdma_get_best_at_port (MM_GENERIC_CDMA (modem), &info->error);
+ if (port)
+ mm_at_serial_port_queue_command (port, "*RESET", 3, NULL, NULL);
+
+ mm_callback_info_schedule (info);
+}
+
static gboolean
grab_port (MMModem *modem,
const char *subsys,
@@ -333,6 +352,7 @@ static void
modem_init (MMModem *modem_class)
{
modem_class->grab_port = grab_port;
+ modem_class->reset = reset;
}
static void
diff --git a/plugins/mm-modem-huawei-cdma.c b/plugins/mm-modem-huawei-cdma.c
index 7faa9f08..3aec470b 100644
--- a/plugins/mm-modem-huawei-cdma.c
+++ b/plugins/mm-modem-huawei-cdma.c
@@ -27,6 +27,7 @@
#include "mm-callback-info.h"
#include "mm-serial-port.h"
#include "mm-serial-parsers.h"
+#include "mm-log.h"
static void modem_init (MMModem *modem_class);
@@ -79,7 +80,7 @@ parse_quality (const char *str, const char *detail)
quality = strtol (str, NULL, 10);
if (errno == 0) {
quality = CLAMP (quality, 0, 100);
- g_debug ("%s: %ld", detail, quality);
+ mm_dbg ("%s: %ld", detail, quality);
return (gint) quality;
}
return -1;
@@ -177,7 +178,7 @@ sysinfo_done (MMAtSerialPort *port,
r = g_regex_new ("\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
if (!r) {
- g_warning ("Huawei(%s): ^SYSINFO parse regex creation failed.", __func__);
+ mm_warn ("Huawei: ^SYSINFO parse regex creation failed.");
goto done;
}
@@ -218,7 +219,7 @@ sysinfo_done (MMAtSerialPort *port,
mm_generic_cdma_query_reg_state_set_callback_1x_state (info, reg_state);
}
} else
- g_warning ("Huawei(%s): failed to parse ^SYSINFO response.", __func__);
+ mm_warn ("Huawei: failed to parse ^SYSINFO response.");
g_match_info_free (match_info);
g_regex_unref (r);
diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c
index cde4b4a2..3fc9ae26 100644
--- a/plugins/mm-modem-huawei-gsm.c
+++ b/plugins/mm-modem-huawei-gsm.c
@@ -29,7 +29,7 @@
#include "mm-callback-info.h"
#include "mm-at-serial-port.h"
#include "mm-serial-parsers.h"
-#include "mm-options.h"
+#include "mm-log.h"
static void modem_init (MMModem *modem_class);
static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class);
@@ -367,6 +367,35 @@ get_band (MMModemGsmNetwork *modem,
mm_at_serial_port_queue_command (port, "AT^SYSCFG?", 3, get_band_done, info);
}
+static MMModemGsmAccessTech
+huawei_sysinfo_to_act (int huawei)
+{
+ switch (huawei) {
+ case 1:
+ return MM_MODEM_GSM_ACCESS_TECH_GSM;
+ case 2:
+ return MM_MODEM_GSM_ACCESS_TECH_GPRS;
+ case 3:
+ return MM_MODEM_GSM_ACCESS_TECH_EDGE;
+ case 4:
+ return MM_MODEM_GSM_ACCESS_TECH_UMTS;
+ case 5:
+ return MM_MODEM_GSM_ACCESS_TECH_HSDPA;
+ case 6:
+ return MM_MODEM_GSM_ACCESS_TECH_HSUPA;
+ case 7:
+ return MM_MODEM_GSM_ACCESS_TECH_HSPA;
+ case 9:
+ return MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS;
+ case 8:
+ /* TD-SCDMA */
+ default:
+ break;
+ }
+
+ return MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
+}
+
static void
get_act_request_done (MMAtSerialPort *port,
GString *response,
@@ -409,22 +438,8 @@ get_act_request_done (MMAtSerialPort *port,
if (srv_stat != 0) {
/* Valid service */
str = g_match_info_fetch (match_info, 7);
- if (str && strlen (str)) {
- if (str[0] == '1')
- act = MM_MODEM_GSM_ACCESS_TECH_GSM;
- else if (str[0] == '2')
- act = MM_MODEM_GSM_ACCESS_TECH_GPRS;
- else if (str[0] == '3')
- act = MM_MODEM_GSM_ACCESS_TECH_EDGE;
- else if (str[0] == '4')
- act = MM_MODEM_GSM_ACCESS_TECH_UMTS;
- else if (str[0] == '5')
- act = MM_MODEM_GSM_ACCESS_TECH_HSDPA;
- else if (str[0] == '6')
- act = MM_MODEM_GSM_ACCESS_TECH_HSUPA;
- else if (str[0] == '7')
- act = MM_MODEM_GSM_ACCESS_TECH_HSPA;
- }
+ if (str && strlen (str))
+ act = huawei_sysinfo_to_act (atoi (str));
g_free (str);
}
@@ -519,7 +534,7 @@ send_huawei_cpin_done (MMAtSerialPort *port,
else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN2))
num = 5;
else {
- g_debug ("%s: unhandled pin type '%s'", __func__, pin_type);
+ mm_dbg ("unhandled pin type '%s'", pin_type);
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type");
}
@@ -561,7 +576,7 @@ get_unlock_retries (MMModemGsmCard *modem,
char *command;
MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- g_debug ("%s: pin type '%s'", __func__, pin_type);
+ mm_dbg ("pin type '%s'", pin_type);
/* Ensure we have a usable port to use for the command */
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
@@ -627,40 +642,30 @@ handle_mode_change (MMAtSerialPort *port,
MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
char *str;
int a;
- int b;
str = g_match_info_fetch (match_info, 1);
a = atoi (str);
g_free (str);
str = g_match_info_fetch (match_info, 2);
- b = atoi (str);
+ act = huawei_sysinfo_to_act (atoi (str));
g_free (str);
if (a == 3) { /* GSM/GPRS mode */
- if (b == 1)
- act = MM_MODEM_GSM_ACCESS_TECH_GSM;
- else if (b == 2)
- act = MM_MODEM_GSM_ACCESS_TECH_GPRS;
- else if (b == 3)
- act = MM_MODEM_GSM_ACCESS_TECH_EDGE;
+ if (act > MM_MODEM_GSM_ACCESS_TECH_EDGE)
+ act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
} else if (a == 5) { /* WCDMA mode */
- if (b == 4)
- act = MM_MODEM_GSM_ACCESS_TECH_UMTS;
- else if (b == 5)
- act = MM_MODEM_GSM_ACCESS_TECH_HSDPA;
- else if (b == 6)
- act = MM_MODEM_GSM_ACCESS_TECH_HSUPA;
- else if (b == 7)
- act = MM_MODEM_GSM_ACCESS_TECH_HSPA;
+ if (act < MM_MODEM_GSM_ACCESS_TECH_UMTS)
+ act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
} else if (a == 0)
act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
else {
- g_warning ("Couldn't parse mode change value: '%s'", str);
+ mm_warn ("Couldn't parse mode change value: '%s'", str);
return;
}
- g_debug ("Access Technology: %d", act);
+ mm_dbg ("Access Technology: %d", act);
+
mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (self), act);
}
@@ -674,10 +679,8 @@ handle_status_change (MMAtSerialPort *port,
str = g_match_info_fetch (match_info, 1);
if (sscanf (str, "%x,%x,%x,%x,%x,%x,%x", &n1, &n2, &n3, &n4, &n5, &n6, &n7)) {
- if (mm_options_debug ()) {
- g_debug ("Duration: %d Up: %d Kbps Down: %d Kbps Total: %d Total: %d\n",
- n1, n2 * 8 / 1000, n3 * 8 / 1000, n4 / 1024, n5 / 1024);
- }
+ mm_dbg ("Duration: %d Up: %d Kbps Down: %d Kbps Total: %d Total: %d\n",
+ n1, n2 * 8 / 1000, n3 * 8 / 1000, n4 / 1024, n5 / 1024);
}
g_free (str);
}
diff --git a/plugins/mm-modem-icera.c b/plugins/mm-modem-icera.c
new file mode 100644
index 00000000..3f71c5b6
--- /dev/null
+++ b/plugins/mm-modem-icera.c
@@ -0,0 +1,794 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ */
+
+/******************************************
+ * Generic utilities for Icera-based modems
+ ******************************************/
+
+#include <config.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include "mm-modem-icera.h"
+
+#include "mm-modem.h"
+#include "mm-errors.h"
+#include "mm-callback-info.h"
+#include "mm-at-serial-port.h"
+#include "mm-generic-gsm.h"
+#include "mm-modem-helpers.h"
+#include "mm-log.h"
+
+struct _MMModemIceraPrivate {
+ /* Pending connection attempt */
+ MMCallbackInfo *connect_pending_data;
+ guint connect_pending_id;
+
+ char *username;
+ char *password;
+
+ MMModemGsmAccessTech last_act;
+};
+
+#define MM_MODEM_ICERA_GET_PRIVATE(m) (MM_MODEM_ICERA_GET_INTERFACE(m)->priv)
+
+static void
+get_allowed_mode_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ gboolean parsed = FALSE;
+
+ if (error)
+ info->error = g_error_copy (error);
+ else if (!g_str_has_prefix (response->str, "%IPSYS: ")) {
+ int a, b;
+
+ if (sscanf (response->str + 8, "%d,%d", &a, &b)) {
+ MMModemGsmAllowedMode mode = MM_MODEM_GSM_ALLOWED_MODE_ANY;
+
+ switch (a) {
+ case 0:
+ mode = MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY;
+ break;
+ case 1:
+ mode = MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY;
+ break;
+ case 2:
+ mode = MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED;
+ break;
+ case 3:
+ mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED;
+ break;
+ default:
+ break;
+ }
+
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (mode), NULL);
+ parsed = TRUE;
+ }
+ }
+
+ if (!error && !parsed)
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse allowed mode results");
+
+ mm_callback_info_schedule (info);
+}
+
+void
+mm_modem_icera_get_allowed_mode (MMModemIcera *self,
+ MMModemUIntFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMAtSerialPort *port;
+
+ info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+
+ port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
+ if (!port) {
+ mm_callback_info_schedule (info);
+ return;
+ }
+ mm_at_serial_port_queue_command (port, "%IPSYS?", 3, get_allowed_mode_done, info);
+}
+
+static void
+set_allowed_mode_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (error)
+ info->error = g_error_copy (error);
+
+ mm_callback_info_schedule (info);
+}
+
+void
+mm_modem_icera_set_allowed_mode (MMModemIcera *self,
+ MMModemGsmAllowedMode mode,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMAtSerialPort *port;
+ char *command;
+ int i;
+
+ info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
+
+ port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
+ if (!port) {
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ switch (mode) {
+ case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY:
+ i = 0;
+ break;
+ case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY:
+ i = 1;
+ break;
+ case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED:
+ i = 2;
+ break;
+ case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED:
+ i = 3;
+ break;
+ case MM_MODEM_GSM_ALLOWED_MODE_ANY:
+ default:
+ i = 5;
+ break;
+ }
+
+ command = g_strdup_printf ("%%IPSYS=%d", i);
+ mm_at_serial_port_queue_command (port, command, 3, set_allowed_mode_done, info);
+ g_free (command);
+}
+
+static MMModemGsmAccessTech
+nwstate_to_act (const char *str)
+{
+ /* small 'g' means CS, big 'G' means PS */
+ if (!strcmp (str, "2G-GPRS"))
+ return MM_MODEM_GSM_ACCESS_TECH_GPRS;
+ else if (!strcmp (str, "2G-EDGE"))
+ return MM_MODEM_GSM_ACCESS_TECH_EDGE;
+ else if (!strcmp (str, "3G"))
+ return MM_MODEM_GSM_ACCESS_TECH_UMTS;
+ else if (!strcmp (str, "3G-HSDPA"))
+ return MM_MODEM_GSM_ACCESS_TECH_HSDPA;
+ else if (!strcmp (str, "3G-HSUPA"))
+ return MM_MODEM_GSM_ACCESS_TECH_HSUPA;
+ else if (!strcmp (str, "3G-HSDPA-HSUPA"))
+ return MM_MODEM_GSM_ACCESS_TECH_HSPA;
+
+ return MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
+}
+
+static void
+nwstate_changed (MMAtSerialPort *port,
+ GMatchInfo *info,
+ gpointer user_data)
+{
+ MMModemIcera *self = MM_MODEM_ICERA (user_data);
+ MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
+ char *str;
+ int rssi = -1;
+
+ str = g_match_info_fetch (info, 1);
+ if (str) {
+ rssi = atoi (str);
+ rssi = CLAMP (rssi, -1, 5);
+ g_free (str);
+ }
+
+ str = g_match_info_fetch (info, 3);
+ if (str) {
+ act = nwstate_to_act (str);
+ g_free (str);
+ }
+
+ MM_MODEM_ICERA_GET_PRIVATE (self)->last_act = act;
+ mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (self), act);
+}
+
+static void
+pacsp_received (MMAtSerialPort *port,
+ GMatchInfo *info,
+ gpointer user_data)
+{
+ return;
+}
+
+static void
+get_nwstate_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+
+ info->error = mm_modem_check_removed (info->modem, error);
+ if (!info->error) {
+ MMModemIcera *self = MM_MODEM_ICERA (info->modem);
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+
+ /* The unsolicited message handler will already have run and
+ * removed the NWSTATE response, so we have to work around that.
+ */
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->last_act), NULL);
+ priv->last_act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
+ }
+
+ mm_callback_info_schedule (info);
+}
+
+void
+mm_modem_icera_get_access_technology (MMModemIcera *self,
+ MMModemUIntFn callback,
+ gpointer user_data)
+{
+ MMAtSerialPort *port;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+
+ port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
+ if (!port) {
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ mm_at_serial_port_queue_command (port, "%NWSTATE=1", 3, get_nwstate_done, info);
+}
+
+/****************************************************************/
+
+static void
+disconnect_ipdpact_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ mm_callback_info_schedule ((MMCallbackInfo *) user_data);
+}
+
+void
+mm_modem_icera_do_disconnect (MMGenericGsm *gsm,
+ gint cid,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMAtSerialPort *primary;
+ char *command;
+
+ info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data);
+
+ primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ command = g_strdup_printf ("%%IPDPACT=%d,0", cid);
+ mm_at_serial_port_queue_command (primary, command, 3, disconnect_ipdpact_done, info);
+ g_free (command);
+}
+
+/*****************************************************************************/
+
+static void
+connect_pending_done (MMModemIcera *self)
+{
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+ GError *error = NULL;
+
+ if (priv->connect_pending_data) {
+ if (priv->connect_pending_data->error) {
+ error = priv->connect_pending_data->error;
+ priv->connect_pending_data->error = NULL;
+ }
+
+ /* Complete the connect */
+ mm_generic_gsm_connect_complete (MM_GENERIC_GSM (self), error, priv->connect_pending_data);
+ priv->connect_pending_data = NULL;
+ }
+
+ if (priv->connect_pending_id) {
+ g_source_remove (priv->connect_pending_id);
+ priv->connect_pending_id = 0;
+ }
+}
+
+static void
+icera_disconnect_done (MMModem *modem,
+ GError *error,
+ gpointer user_data)
+{
+ mm_info ("Modem signaled disconnection from the network");
+}
+
+static void
+connection_enabled (MMAtSerialPort *port,
+ GMatchInfo *match_info,
+ gpointer user_data)
+{
+ MMModemIcera *self = MM_MODEM_ICERA (user_data);
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+ MMCallbackInfo *info = priv->connect_pending_data;
+ char *str;
+ int status, cid, tmp;
+
+ cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (self));
+ if (cid < 0)
+ return;
+
+ str = g_match_info_fetch (match_info, 1);
+ g_return_if_fail (str != NULL);
+ tmp = atoi (str);
+ g_free (str);
+
+ /* Make sure the unsolicited message's CID matches the current CID */
+ if (tmp != cid)
+ return;
+
+ str = g_match_info_fetch (match_info, 2);
+ g_return_if_fail (str != NULL);
+ status = atoi (str);
+ g_free (str);
+
+ switch (status) {
+ case 0:
+ /* Disconnected */
+ if (mm_modem_get_state (MM_MODEM (self)) >= MM_MODEM_STATE_CONNECTED)
+ mm_modem_disconnect (MM_MODEM (self), icera_disconnect_done, NULL);
+ break;
+ case 1:
+ /* Connected */
+ connect_pending_done (self);
+ break;
+ case 2:
+ /* Connecting */
+ break;
+ case 3:
+ /* Call setup failure? */
+ if (info) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "Call setup failed");
+ }
+ connect_pending_done (self);
+ break;
+ default:
+ mm_warn ("Unknown Icera connect status %d", status);
+ break;
+ }
+}
+
+/****************************************************************/
+
+static gint
+_get_cid (MMModemIcera *self)
+{
+ gint cid;
+
+ cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (self));
+ if (cid < 0) {
+ g_warn_if_fail (cid >= 0);
+ cid = 0;
+ }
+ return cid;
+}
+
+static void
+icera_call_control (MMModemIcera *self,
+ gboolean activate,
+ MMAtSerialResponseFn callback,
+ gpointer user_data)
+{
+ char *command;
+ MMAtSerialPort *primary;
+
+ primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ command = g_strdup_printf ("%%IPDPACT=%d,%d", _get_cid (self), activate ? 1 : 0);
+ mm_at_serial_port_queue_command (primary, command, 3, callback, user_data);
+ g_free (command);
+}
+
+static void
+timeout_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ connect_pending_done (MM_MODEM_ICERA (user_data));
+}
+
+static gboolean
+icera_connect_timed_out (gpointer data)
+{
+ MMModemIcera *self = MM_MODEM_ICERA (data);
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+ MMCallbackInfo *info = priv->connect_pending_data;
+
+ priv->connect_pending_id = 0;
+
+ if (info) {
+ info->error = g_error_new_literal (MM_SERIAL_ERROR,
+ MM_SERIAL_ERROR_RESPONSE_TIMEOUT,
+ "Connection timed out");
+ }
+
+ icera_call_control (self, FALSE, timeout_done, self);
+ return FALSE;
+}
+
+static void
+icera_enabled (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (error) {
+ mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), error, info);
+ } else {
+ MMModemIcera *self = MM_MODEM_ICERA (info->modem);
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+
+ g_warn_if_fail (priv->connect_pending_id == 0);
+ if (priv->connect_pending_id)
+ g_source_remove (priv->connect_pending_id);
+
+ priv->connect_pending_data = info;
+ priv->connect_pending_id = g_timeout_add_seconds (30, icera_connect_timed_out, self);
+ }
+}
+
+static void
+old_context_clear_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ /* Activate the PDP context and start the data session */
+ icera_call_control (MM_MODEM_ICERA (info->modem), TRUE, icera_enabled, info);
+}
+
+static void
+auth_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (error)
+ mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), error, info);
+ else {
+ /* Ensure the PDP context is deactivated */
+ icera_call_control (MM_MODEM_ICERA (info->modem), FALSE, old_context_clear_done, info);
+ }
+}
+
+void
+mm_modem_icera_do_connect (MMModemIcera *self,
+ const char *number,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMModem *modem = MM_MODEM (self);
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+ MMCallbackInfo *info;
+ MMAtSerialPort *primary;
+ gint cid;
+ char *command;
+
+ mm_modem_set_state (modem, MM_MODEM_STATE_CONNECTING, MM_MODEM_STATE_REASON_NONE);
+
+ info = mm_callback_info_new (modem, callback, user_data);
+
+ primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ cid = _get_cid (self);
+
+
+ /* Both user and password are required; otherwise firmware returns an error */
+ if (!priv->username || !priv->password)
+ command = g_strdup_printf ("%%IPDPCFG=%d,0,0,\"\",\"\"", cid);
+ else {
+ command = g_strdup_printf ("%%IPDPCFG=%d,0,1,\"%s\",\"%s\"",
+ cid,
+ priv->password ? priv->password : "",
+ priv->username ? priv->username : "");
+
+ }
+
+ mm_at_serial_port_queue_command (primary, command, 3, auth_done, info);
+ g_free (command);
+}
+
+/****************************************************************/
+
+
+static void
+free_dns_array (gpointer data)
+{
+ g_array_free ((GArray *) data, TRUE);
+}
+
+static void
+ip4_config_invoke (MMCallbackInfo *info)
+{
+ MMModemIp4Fn callback = (MMModemIp4Fn) info->callback;
+
+ callback (info->modem,
+ GPOINTER_TO_UINT (mm_callback_info_get_data (info, "ip4-address")),
+ (GArray *) mm_callback_info_get_data (info, "ip4-dns"),
+ info->error, info->user_data);
+}
+
+#define IPDPADDR_TAG "%IPDPADDR: "
+
+static void
+get_ip4_config_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ char **items, **iter;
+ GArray *dns_array;
+ int i;
+ guint32 tmp;
+ gint cid;
+
+ if (error) {
+ info->error = g_error_copy (error);
+ goto out;
+ } else if (!g_str_has_prefix (response->str, IPDPADDR_TAG)) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Retrieving failed: invalid response.");
+ goto out;
+ }
+
+ cid = _get_cid (MM_MODEM_ICERA (info->modem));
+ dns_array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 2);
+
+ /* %IPDPADDR: <cid>,<ip>,<gw>,<dns1>,<dns2>[,<nbns1>,<nbns2>] */
+ items = g_strsplit (response->str + strlen (IPDPADDR_TAG), ", ", 0);
+
+ for (iter = items, i = 0; *iter; iter++, i++) {
+ if (i == 0) { /* CID */
+ long int num;
+
+ errno = 0;
+ num = strtol (*iter, NULL, 10);
+ if (errno != 0 || num < 0 || (gint) num != cid) {
+ info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Unknown CID in IPDPADDR response ("
+ "got %d, expected %d)", (guint) num, cid);
+ break;
+ }
+ } else if (i == 1) { /* IP address */
+ if (inet_pton (AF_INET, *iter, &tmp) > 0)
+ mm_callback_info_set_data (info, "ip4-address", GUINT_TO_POINTER (tmp), NULL);
+ } else if (i == 3) { /* DNS 1 */
+ if (inet_pton (AF_INET, *iter, &tmp) > 0)
+ g_array_append_val (dns_array, tmp);
+ } else if (i == 4) { /* DNS 2 */
+ if (inet_pton (AF_INET, *iter, &tmp) > 0)
+ g_array_append_val (dns_array, tmp);
+ }
+ }
+
+ g_strfreev (items);
+ mm_callback_info_set_data (info, "ip4-dns", dns_array, free_dns_array);
+
+ out:
+ mm_callback_info_schedule (info);
+}
+
+void
+mm_modem_icera_get_ip4_config (MMModemIcera *self,
+ MMModemIp4Fn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ char *command;
+ MMAtSerialPort *primary;
+
+ info = mm_callback_info_new_full (MM_MODEM (self),
+ ip4_config_invoke,
+ G_CALLBACK (callback),
+ user_data);
+
+ primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ command = g_strdup_printf ("%%IPDPADDR=%d", _get_cid (self));
+ mm_at_serial_port_queue_command (primary, command, 3, get_ip4_config_done, info);
+ g_free (command);
+}
+
+/****************************************************************/
+
+static const char *
+get_string_property (GHashTable *properties, const char *name)
+{
+ GValue *value;
+
+ value = (GValue *) g_hash_table_lookup (properties, name);
+ if (value && G_VALUE_HOLDS_STRING (value))
+ return g_value_get_string (value);
+ return NULL;
+}
+
+void
+mm_modem_icera_simple_connect (MMModemIcera *self, GHashTable *properties)
+{
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+
+ g_free (priv->username);
+ priv->username = g_strdup (get_string_property (properties, "username"));
+ g_free (priv->password);
+ priv->password = g_strdup (get_string_property (properties, "password"));
+}
+
+/****************************************************************/
+
+void
+mm_modem_icera_register_unsolicted_handlers (MMModemIcera *self,
+ MMAtSerialPort *port)
+{
+ GRegex *regex;
+
+ /* %NWSTATE: <rssi>,<mccmnc>,<tech>,<connected>,<regulation> */
+ regex = g_regex_new ("\\r\\n%NWSTATE:\\s*(\\d+),(\\d+),([^,]*),([^,]*),(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_at_serial_port_add_unsolicited_msg_handler (port, regex, nwstate_changed, self, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\+PACSP(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_at_serial_port_add_unsolicited_msg_handler (port, regex, pacsp_received, self, NULL);
+ g_regex_unref (regex);
+
+ /* %IPDPACT: <cid>,<status>,0 */
+ regex = g_regex_new ("\\r\\n%IPDPACT:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_at_serial_port_add_unsolicited_msg_handler (port, regex, connection_enabled, self, NULL);
+ g_regex_unref (regex);
+}
+
+void
+mm_modem_icera_change_unsolicited_messages (MMModemIcera *self, gboolean enabled)
+{
+ MMAtSerialPort *primary;
+
+ primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ mm_at_serial_port_queue_command (primary, enabled ? "%NWSTATE=1" : "%NWSTATE=0", 3, NULL, NULL);
+}
+
+/****************************************************************/
+
+static void
+is_icera_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+
+ info->error = mm_modem_check_removed (info->modem, error);
+ if (!info->error)
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (TRUE), NULL);
+ mm_callback_info_schedule (info);
+}
+
+void
+mm_modem_icera_is_icera (MMModemIcera *self,
+ MMModemUIntFn callback,
+ gpointer user_data)
+{
+ MMAtSerialPort *port;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+
+ port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
+ if (!port) {
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ mm_at_serial_port_queue_command (port, "%IPSYS?", 5, is_icera_done, info);
+}
+
+/****************************************************************/
+
+void
+mm_modem_icera_prepare (MMModemIcera *self)
+{
+ self->priv = g_malloc0 (sizeof (MMModemIceraPrivate));
+}
+
+void
+mm_modem_icera_cleanup (MMModemIcera *self)
+{
+ MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self);
+
+ /* Clear the pending connection if necessary */
+ connect_pending_done (self);
+
+ g_free (priv->username);
+ g_free (priv->password);
+
+ memset (priv, 0, sizeof (MMModemIceraPrivate));
+ g_free (priv);
+}
+
+static void
+mm_modem_icera_init (gpointer g_iface)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+ }
+}
+
+GType
+mm_modem_icera_get_type (void)
+{
+ static GType icera_type = 0;
+
+ if (!G_UNLIKELY (icera_type)) {
+ const GTypeInfo icera_info = {
+ sizeof (MMModemIcera), /* class_size */
+ mm_modem_icera_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL
+ };
+
+ icera_type = g_type_register_static (G_TYPE_INTERFACE,
+ "MMModemIcera",
+ &icera_info, 0);
+
+ g_type_interface_add_prerequisite (icera_type, MM_TYPE_MODEM);
+ }
+
+ return icera_type;
+}
+
diff --git a/plugins/mm-modem-icera.h b/plugins/mm-modem-icera.h
new file mode 100644
index 00000000..71258d2a
--- /dev/null
+++ b/plugins/mm-modem-icera.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ */
+
+/******************************************
+ * Generic utilities for Icera-based modems
+ ******************************************/
+
+#ifndef MM_MODEM_ICERA_H
+#define MM_MODEM_ICERA_H
+
+#include <glib-object.h>
+
+#include "mm-modem-gsm.h"
+#include "mm-generic-gsm.h"
+
+#define MM_TYPE_MODEM_ICERA (mm_modem_icera_get_type ())
+#define MM_MODEM_ICERA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_ICERA, MMModemIcera))
+#define MM_IS_MODEM_ICERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_ICERA))
+#define MM_MODEM_ICERA_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM_ICERA, MMModemIcera))
+
+typedef struct _MMModemIceraPrivate MMModemIceraPrivate;
+
+typedef struct _MMModemIcera MMModemIcera;
+
+struct _MMModemIcera {
+ GTypeInterface g_iface;
+
+ MMModemIceraPrivate *priv;
+};
+
+GType mm_modem_icera_get_type (void);
+
+void mm_modem_icera_prepare (MMModemIcera *self);
+
+void mm_modem_icera_cleanup (MMModemIcera *self);
+
+void mm_modem_icera_get_allowed_mode (MMModemIcera *self,
+ MMModemUIntFn callback,
+ gpointer user_data);
+
+void mm_modem_icera_set_allowed_mode (MMModemIcera *self,
+ MMModemGsmAllowedMode mode,
+ MMModemFn callback,
+ gpointer user_data);
+
+void mm_modem_icera_register_unsolicted_handlers (MMModemIcera *self,
+ MMAtSerialPort *port);
+
+void mm_modem_icera_change_unsolicited_messages (MMModemIcera *self,
+ gboolean enabled);
+
+void mm_modem_icera_get_access_technology (MMModemIcera *self,
+ MMModemUIntFn callback,
+ gpointer user_data);
+
+void mm_modem_icera_is_icera (MMModemIcera *self,
+ MMModemUIntFn callback,
+ gpointer user_data);
+
+void mm_modem_icera_do_disconnect (MMGenericGsm *gsm,
+ gint cid,
+ MMModemFn callback,
+ gpointer user_data);
+
+void mm_modem_icera_simple_connect (MMModemIcera *self, GHashTable *properties);
+
+void mm_modem_icera_do_connect (MMModemIcera *self,
+ const char *number,
+ MMModemFn callback,
+ gpointer user_data);
+
+void mm_modem_icera_get_ip4_config (MMModemIcera *self,
+ MMModemIp4Fn callback,
+ gpointer user_data);
+
+#endif /* MM_MODEM_ICERA_H */
+
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index 53e98ba6..93034537 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -1,7 +1,7 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2008 - 2010 Ericsson AB
- * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ * Copyright (C) 2009 - 2011 Red Hat, Inc.
*
* Author: Per Hallsmark <per.hallsmark@ericsson.com>
* Bjorn Runaker <bjorn.runaker@ericsson.com>
@@ -31,6 +31,7 @@
#include "mm-modem-gsm-card.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
+#include "mm-log.h"
static void modem_init (MMModem *modem_class);
static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class);
@@ -410,7 +411,7 @@ mbm_emrdy_done (MMAtSerialPort *port,
MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (info->modem);
if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT))
- g_warning ("%s: timed out waiting for EMRDY response.", __func__);
+ mm_warn ("timed out waiting for EMRDY response.");
else
priv->have_emrdy = TRUE;
@@ -510,6 +511,24 @@ do_disconnect (MMGenericGsm *gsm,
}
static void
+reset (MMModem *modem,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMAtSerialPort *port;
+
+ info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
+
+ /* Ensure we have a usable port to use for the command */
+ port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
+ if (port)
+ mm_at_serial_port_queue_command (port, "*E2RESET", 3, NULL, NULL);
+
+ mm_callback_info_schedule (info);
+}
+
+static void
factory_reset_done (MMAtSerialPort *port,
GString *response,
GError *error,
@@ -614,16 +633,16 @@ mbm_e2nap_received (MMAtSerialPort *port,
g_free (str);
if (MBM_E2NAP_DISCONNECTED == state) {
- g_debug ("%s: disconnected", __func__);
+ mm_dbg ("disconnected");
mbm_do_connect_done (MM_MODEM_MBM (user_data), FALSE);
} else if (MBM_E2NAP_CONNECTED == state) {
- g_debug ("%s: connected", __func__);
+ mm_dbg ("connected");
mbm_do_connect_done (MM_MODEM_MBM (user_data), TRUE);
} else if (MBM_E2NAP_CONNECTING == state)
- g_debug("%s: connecting", __func__);
+ mm_dbg ("connecting");
else {
/* Should not happen */
- g_debug("%s: unhandled E2NAP state %d", __func__, state);
+ mm_dbg ("unhandled E2NAP state %d", state);
mbm_do_connect_done (MM_MODEM_MBM (user_data), FALSE);
}
}
@@ -793,7 +812,7 @@ send_epin_done (MMAtSerialPort *port,
else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK2))
sscanf (response->str, "*EPIN: %*d, %*d, %*d, %d", &attempts_left);
else {
- g_debug ("%s: unhandled pin type '%s'", __func__, pin_type);
+ mm_dbg ("unhandled pin type '%s'", pin_type);
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type");
}
@@ -820,7 +839,7 @@ mbm_get_unlock_retries (MMModemGsmCard *modem,
char *command;
MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- g_debug ("%s: pin type '%s'", __func__, pin_type);
+ mm_dbg ("pin type '%s'", pin_type);
/* Ensure we have a usable port to use for the command */
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
@@ -940,6 +959,7 @@ modem_init (MMModem *modem_class)
modem_class->grab_port = grab_port;
modem_class->disable = disable;
modem_class->connect = do_connect;
+ modem_class->reset = reset;
modem_class->factory_reset = factory_reset;
}
diff --git a/plugins/mm-modem-zte.c b/plugins/mm-modem-zte.c
index 558260ec..c447c58f 100644
--- a/plugins/mm-modem-zte.c
+++ b/plugins/mm-modem-zte.c
@@ -24,11 +24,17 @@
#include "mm-errors.h"
#include "mm-callback-info.h"
#include "mm-modem-helpers.h"
+#include "mm-modem-simple.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 *simple_class);
G_DEFINE_TYPE_EXTENDED (MMModemZte, mm_modem_zte, MM_TYPE_GENERIC_GSM, 0,
- G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init))
+ 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_ZTE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_ZTE, MMModemZtePrivate))
@@ -36,6 +42,7 @@ typedef struct {
gboolean init_retried;
guint32 cpms_tries;
guint cpms_timeout;
+ gboolean is_icera;
} MMModemZtePrivate;
MMModem *
@@ -149,9 +156,15 @@ get_allowed_mode (MMGenericGsm *gsm,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMModemZte *self = MM_MODEM_ZTE (gsm);
MMCallbackInfo *info;
MMAtSerialPort *port;
+ if (MM_MODEM_ZTE_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);
port = mm_generic_gsm_get_best_at_port (gsm, &info->error);
@@ -183,11 +196,17 @@ set_allowed_mode (MMGenericGsm *gsm,
MMModemFn callback,
gpointer user_data)
{
+ MMModemZte *self = MM_MODEM_ZTE (gsm);
MMCallbackInfo *info;
MMAtSerialPort *port;
char *command;
int cm_mode = 0, pref_acq = 0;
+ if (MM_MODEM_ZTE_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);
port = mm_generic_gsm_get_best_at_port (gsm, &info->error);
@@ -248,16 +267,22 @@ get_act_request_done (MMAtSerialPort *port,
}
static void
-get_access_technology (MMGenericGsm *modem,
+get_access_technology (MMGenericGsm *gsm,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMModemZte *self = MM_MODEM_ZTE (gsm);
MMAtSerialPort *port;
MMCallbackInfo *info;
- info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+ if (MM_MODEM_ZTE_GET_PRIVATE (self)->is_icera) {
+ mm_modem_icera_get_access_technology (MM_MODEM_ICERA (self), callback, user_data);
+ return;
+ }
- port = mm_generic_gsm_get_best_at_port (modem, &info->error);
+ info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data);
+
+ port = mm_generic_gsm_get_best_at_port (gsm, &info->error);
if (!port) {
mm_callback_info_schedule (info);
return;
@@ -266,6 +291,21 @@ get_access_technology (MMGenericGsm *modem,
mm_at_serial_port_queue_command (port, "+ZPAS?", 3, get_act_request_done, info);
}
+static void
+do_disconnect (MMGenericGsm *gsm,
+ gint cid,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMModemZte *self = MM_MODEM_ZTE (gsm);
+ MMModemZtePrivate *priv = MM_MODEM_ZTE_GET_PRIVATE (self);
+
+ if (priv->is_icera)
+ mm_modem_icera_do_disconnect (gsm, cid, callback, user_data);
+ else
+ MM_GENERIC_GSM_CLASS (mm_modem_zte_parent_class)->do_disconnect (gsm, cid, callback, user_data);
+}
+
/*****************************************************************************/
/* Modem class override functions */
/*****************************************************************************/
@@ -314,6 +354,10 @@ cpms_try_done (MMAtSerialPort *port,
}
}
+ /* Turn on unsolicited network state messages */
+ if (priv->is_icera)
+ mm_modem_icera_change_unsolicited_messages (MM_MODEM_ICERA (info->modem), TRUE);
+
mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info);
}
@@ -325,6 +369,8 @@ init_modem_done (MMAtSerialPort *port,
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ mm_at_serial_port_queue_command (port, "E0", 5, NULL, NULL);
+
/* Attempt to disable floods of "+ZUSIMR:2" unsolicited responses that
* eventually fill up the device's buffers and make it crash. Normally
* done during probing, but if the device has a PIN enabled it won't
@@ -338,13 +384,33 @@ static void enable_flash_done (MMSerialPort *port,
gpointer user_data);
static void
+icera_check_cb (MMModem *modem,
+ guint32 result,
+ GError *error,
+ gpointer user_data)
+{
+ if (!error) {
+ MMModemZte *self = MM_MODEM_ZTE (user_data);
+ MMModemZtePrivate *priv = MM_MODEM_ZTE_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);
+ }
+ }
+}
+
+static void
pre_init_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- MMModemZtePrivate *priv = MM_MODEM_ZTE_GET_PRIVATE (info->modem);
+ MMModemZte *self = MM_MODEM_ZTE (info->modem);
+ MMModemZtePrivate *priv = MM_MODEM_ZTE_GET_PRIVATE (self);
if (error) {
/* Retry the init string one more time; the modem sometimes throws it away */
@@ -353,9 +419,10 @@ pre_init_done (MMAtSerialPort *port,
priv->init_retried = TRUE;
enable_flash_done (MM_SERIAL_PORT (port), NULL, user_data);
} else
- mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info);
+ mm_generic_gsm_enable_complete (MM_GENERIC_GSM (self), error, info);
} else {
/* Finish the initialization */
+ mm_modem_icera_is_icera (MM_MODEM_ICERA (self), icera_check_cb, self);
mm_at_serial_port_queue_command (port, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;", 10, init_modem_done, info);
}
}
@@ -387,21 +454,112 @@ do_enable (MMGenericGsm *modem, MMModemFn callback, gpointer user_data)
mm_serial_port_flash (MM_SERIAL_PORT (primary), 100, FALSE, enable_flash_done, info);
}
+/*****************************************************************************/
+
+typedef struct {
+ MMModem *modem;
+ MMModemFn callback;
+ gpointer user_data;
+} DisableInfo;
+
+static void
+disable_unsolicited_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+
+{
+ MMModem *parent_modem_iface;
+ DisableInfo *info = user_data;
+
+ parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (info->modem));
+ parent_modem_iface->disable (info->modem, info->callback, info->user_data);
+ g_free (info);
+}
+
static void
disable (MMModem *modem,
MMModemFn callback,
gpointer user_data)
{
MMModemZtePrivate *priv = MM_MODEM_ZTE_GET_PRIVATE (modem);
- MMModem *parent_modem_iface;
+ MMAtSerialPort *primary;
+ DisableInfo *info;
priv->init_retried = FALSE;
- /* Do the normal disable stuff */
- parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (modem));
- parent_modem_iface->disable (modem, callback, user_data);
+ info = g_malloc0 (sizeof (DisableInfo));
+ info->callback = callback;
+ info->user_data = user_data;
+ info->modem = modem;
+
+ 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);
+}
+
+/*****************************************************************************/
+
+static void
+do_connect (MMModem *modem,
+ const char *number,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMModem *parent_iface;
+
+ if (MM_MODEM_ZTE_GET_PRIVATE (modem)->is_icera)
+ mm_modem_icera_do_connect (MM_MODEM_ICERA (modem), number, callback, user_data);
+ else {
+ parent_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (modem));
+ parent_iface->connect (MM_MODEM (modem), number, callback, user_data);
+ }
+}
+
+static void
+get_ip4_config (MMModem *modem,
+ MMModemIp4Fn callback,
+ gpointer user_data)
+{
+ MMModem *parent_iface;
+
+ if (MM_MODEM_ZTE_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 (MM_MODEM (modem), callback, user_data);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+simple_connect (MMModemSimple *simple,
+ GHashTable *properties,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMModemZtePrivate *priv = MM_MODEM_ZTE_GET_PRIVATE (simple);
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemSimple *parent_iface;
+
+ if (priv->is_icera)
+ mm_modem_icera_simple_connect (MM_MODEM_ICERA (simple), properties);
+
+ parent_iface = g_type_interface_peek_parent (MM_MODEM_SIMPLE_GET_INTERFACE (simple));
+ parent_iface->connect (MM_MODEM_SIMPLE (simple), properties, callback, info);
}
+/*****************************************************************************/
+
static gboolean
grab_port (MMModem *modem,
const char *subsys,
@@ -451,6 +609,9 @@ grab_port (MMModem *modem,
regex = g_regex_new ("\\r\\n\\+ZEND\\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));
}
return !!port;
@@ -462,10 +623,24 @@ static void
modem_init (MMModem *modem_class)
{
modem_class->disable = disable;
+ modem_class->connect = do_connect;
+ modem_class->get_ip4_config = get_ip4_config;
modem_class->grab_port = grab_port;
}
static void
+modem_icera_init (MMModemIcera *icera_class)
+{
+ mm_modem_icera_prepare (icera_class);
+}
+
+static void
+modem_simple_init (MMModemSimple *class)
+{
+ class->connect = simple_connect;
+}
+
+static void
mm_modem_zte_init (MMModemZte *self)
{
}
@@ -478,6 +653,10 @@ dispose (GObject *object)
if (priv->cpms_timeout)
g_source_remove (priv->cpms_timeout);
+
+ mm_modem_icera_cleanup (MM_MODEM_ICERA (self));
+
+ G_OBJECT_CLASS (mm_modem_zte_parent_class)->dispose (object);
}
static void
@@ -491,6 +670,7 @@ mm_modem_zte_class_init (MMModemZteClass *klass)
object_class->dispose = dispose;
gsm_class->do_enable = do_enable;
+ gsm_class->do_disconnect = do_disconnect;
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;
gsm_class->get_access_technology = get_access_technology;
diff --git a/plugins/mm-plugin-generic.c b/plugins/mm-plugin-generic.c
index 9704ae84..a27704b4 100644
--- a/plugins/mm-plugin-generic.c
+++ b/plugins/mm-plugin-generic.c
@@ -31,6 +31,7 @@
#include "mm-generic-cdma.h"
#include "mm-errors.h"
#include "mm-serial-parsers.h"
+#include "mm-log.h"
G_DEFINE_TYPE (MMPluginGeneric, mm_plugin_generic, MM_TYPE_PLUGIN_BASE)
@@ -127,10 +128,10 @@ grab_port (MMPluginBase *base,
g_set_error (error, 0, 0, "Could not get port's sysfs file.");
return NULL;
} else {
- g_message ("%s: (%s/%s) WARNING: missing udev 'device' file",
- mm_plugin_get_name (MM_PLUGIN (base)),
- subsys,
- name);
+ mm_warn ("%s: (%s/%s) WARNING: missing udev 'device' file",
+ mm_plugin_get_name (MM_PLUGIN (base)),
+ subsys,
+ name);
}
}
diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c
index 090bb0d5..f1590ca3 100644
--- a/plugins/mm-plugin-huawei.c
+++ b/plugins/mm-plugin-huawei.c
@@ -27,6 +27,7 @@
#include "mm-modem-huawei-cdma.h"
#include "mm-serial-parsers.h"
#include "mm-at-serial-port.h"
+#include "mm-log.h"
G_DEFINE_TYPE (MMPluginHuawei, mm_plugin_huawei, MM_TYPE_PLUGIN_BASE)
@@ -240,10 +241,10 @@ supports_port (MMPluginBase *base,
info->id = g_timeout_add_seconds (7, probe_secondary_timeout, task);
if (!mm_serial_port_open (MM_SERIAL_PORT (info->serial), &error)) {
- g_warning ("%s: (Huawei) %s: couldn't open serial port: (%d) %s",
- __func__, name,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
+ 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;
diff --git a/plugins/mm-plugin-mbm.c b/plugins/mm-plugin-mbm.c
index dd64cc66..6684ff9a 100644
--- a/plugins/mm-plugin-mbm.c
+++ b/plugins/mm-plugin-mbm.c
@@ -84,7 +84,7 @@ supports_port (MMPluginBase *base,
client = g_udev_client_new (sys);
if (!client) {
- g_warning ("mbm: could not get udev client.");
+ g_warn_if_fail (client != NULL);
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
diff --git a/plugins/mm-plugin-zte.c b/plugins/mm-plugin-zte.c
index 97bbcc36..bb2ee176 100644
--- a/plugins/mm-plugin-zte.c
+++ b/plugins/mm-plugin-zte.c
@@ -11,7 +11,7 @@
* GNU General Public License for more details:
*
* Copyright (C) 2008 - 2009 Novell, Inc.
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 - 2010 Red Hat, Inc.
*/
#include <string.h>
@@ -73,9 +73,6 @@ supports_port (MMPluginBase *base,
/* Can't do anything with non-serial ports */
port = mm_plugin_base_supports_task_get_port (task);
- if (strcmp (g_udev_device_get_subsystem (port), "tty"))
- return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
-
subsys = g_udev_device_get_subsystem (port);
name = g_udev_device_get_name (port);
@@ -85,6 +82,20 @@ supports_port (MMPluginBase *base,
if (vendor != 0x19d2)
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ if (!strcmp (subsys, "net")) {
+ /* If we don't know the modem's type yet, defer grabbing the port
+ * until we know the type.
+ */
+ if (!existing)
+ return MM_PLUGIN_SUPPORTS_PORT_DEFER;
+
+ mm_plugin_base_supports_task_complete (task, 10);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+
+ if (strcmp (subsys, "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
level = get_level_for_capabilities (cached);
if (level) {
@@ -165,7 +176,7 @@ grab_port (MMPluginBase *base,
return NULL;
}
}
- } else if (get_level_for_capabilities (caps)) {
+ } else if (get_level_for_capabilities (caps) || (!strcmp (subsys, "net"))) {
if (caps & MM_PLUGIN_BASE_PORT_CAP_QCDM)
ptype = MM_PORT_TYPE_QCDM;
diff --git a/src/77-mm-usb-device-blacklist.rules b/src/77-mm-usb-device-blacklist.rules
index 78a6770d..58b0cee6 100644
--- a/src/77-mm-usb-device-blacklist.rules
+++ b/src/77-mm-usb-device-blacklist.rules
@@ -62,5 +62,11 @@ ATTRS{idVendor}=="0592", ATTRS{idProduct}=="0002", ENV{ID_MM_DEVICE_IGNORE}="1"
# that isn't blacklisted.
ATTRS{idVendor}=="0830", ATTRS{idProduct}=="0061", ENV{ID_MM_DEVICE_IGNORE}="1"
+# Belkin F5U183 Serial Adapter (unlikely to have a modem behind it)
+ATTRS{idVendor}=="050d", ATTRS{idProduct}=="0103", ENV{ID_MM_DEVICE_IGNORE}="1"
+
+# ATEN Intl UC-232A (Prolific)
+ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", ENV{ID_MM_DEVICE_IGNORE}="1"
+
LABEL="mm_usb_device_blacklist_end"
diff --git a/src/Makefile.am b/src/Makefile.am
index 3e656d81..e813e7e8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -81,6 +81,8 @@ endif
modem_manager_SOURCES = \
main.c \
+ mm-log.c \
+ mm-log.h \
mm-callback-info.c \
mm-callback-info.h \
$(auth_sources) \
@@ -109,8 +111,6 @@ modem_manager_SOURCES = \
mm-modem-gsm-ussd.h \
mm-modem-simple.c \
mm-modem-simple.h \
- mm-options.c \
- mm-options.h \
mm-plugin.c \
mm-plugin.h \
mm-plugin-base.c \
diff --git a/src/main.c b/src/main.c
index 2b4da21d..0f8119ee 100644
--- a/src/main.c
+++ b/src/main.c
@@ -11,7 +11,7 @@
* GNU General Public License for more details:
*
* Copyright (C) 2008 - 2009 Novell, Inc.
- * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ * Copyright (C) 2009 - 2011 Red Hat, Inc.
*/
#include <config.h>
@@ -21,8 +21,10 @@
#include <unistd.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
+#include <stdlib.h>
+
#include "mm-manager.h"
-#include "mm-options.h"
+#include "mm-log.h"
#if !defined(MM_DIST_VERSION)
# define MM_DIST_VERSION VERSION
@@ -34,9 +36,9 @@ static void
mm_signal_handler (int signo)
{
if (signo == SIGUSR1)
- mm_options_set_debug (!mm_options_debug ());
+ mm_log_usr1 ();
else if (signo == SIGINT || signo == SIGTERM) {
- g_message ("Caught signal %d, shutting down...", signo);
+ mm_info ("Caught signal %d, shutting down...", signo);
if (loop)
g_main_loop_quit (loop);
else
@@ -60,64 +62,9 @@ setup_signals (void)
}
static void
-log_handler (const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer ignored)
-{
- int syslog_priority;
-
- switch (log_level) {
- case G_LOG_LEVEL_ERROR:
- syslog_priority = LOG_CRIT;
- break;
-
- case G_LOG_LEVEL_CRITICAL:
- syslog_priority = LOG_ERR;
- break;
-
- case G_LOG_LEVEL_WARNING:
- syslog_priority = LOG_WARNING;
- break;
-
- case G_LOG_LEVEL_MESSAGE:
- syslog_priority = LOG_NOTICE;
- break;
-
- case G_LOG_LEVEL_DEBUG:
- syslog_priority = LOG_DEBUG;
- break;
-
- case G_LOG_LEVEL_INFO:
- default:
- syslog_priority = LOG_INFO;
- break;
- }
-
- syslog (syslog_priority, "%s", message);
-}
-
-
-static void
-logging_setup (void)
-{
- openlog (G_LOG_DOMAIN, LOG_CONS, LOG_DAEMON);
- g_log_set_handler (G_LOG_DOMAIN,
- G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
- log_handler,
- NULL);
-}
-
-static void
-logging_shutdown (void)
-{
- closelog ();
-}
-
-static void
destroy_cb (DBusGProxy *proxy, gpointer user_data)
{
- g_message ("disconnected from the system bus, exiting.");
+ mm_warn ("disconnected from the system bus, exiting.");
g_main_loop_quit (loop);
}
@@ -139,16 +86,16 @@ create_dbus_proxy (DBusGConnection *bus)
G_TYPE_INVALID,
G_TYPE_UINT, &request_name_result,
G_TYPE_INVALID)) {
- g_warning ("Could not acquire the %s service.\n"
- " Message: '%s'", MM_DBUS_SERVICE, err->message);
+ mm_warn ("Could not acquire the %s service.\n"
+ " Message: '%s'", MM_DBUS_SERVICE, err->message);
g_error_free (err);
g_object_unref (proxy);
proxy = NULL;
} else if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
- g_warning ("Could not acquire the " MM_DBUS_SERVICE
- " service as it is already taken. Return: %d",
- request_name_result);
+ mm_warn ("Could not acquire the " MM_DBUS_SERVICE
+ " service as it is already taken. Return: %d",
+ request_name_result);
g_object_unref (proxy);
proxy = NULL;
@@ -175,17 +122,49 @@ main (int argc, char *argv[])
DBusGProxy *proxy;
MMManager *manager;
GError *err = NULL;
+ GOptionContext *opt_ctx;
guint id;
+ const char *log_level = NULL, *log_file = NULL;
+ gboolean debug = FALSE, show_ts = FALSE, rel_ts = FALSE;
+
+ GOptionEntry entries[] = {
+ { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Output to console rather than syslog", NULL },
+ { "log-level", 0, 0, G_OPTION_ARG_STRING, &log_level, "Log level: one of [ERR, WARN, INFO, DEBUG]", "INFO" },
+ { "log-file", 0, 0, G_OPTION_ARG_STRING, &log_file, "Path to log file", NULL },
+ { "timestamps", 0, 0, G_OPTION_ARG_NONE, &show_ts, "Show timestamps in log output", NULL },
+ { "relative-timestamps", 0, 0, G_OPTION_ARG_NONE, &rel_ts, "Use relative timestamps (from MM start)", NULL },
+ { NULL }
+ };
- mm_options_parse (argc, argv);
g_type_init ();
- setup_signals ();
+ opt_ctx = g_option_context_new (NULL);
+ g_option_context_set_summary (opt_ctx, "DBus system service to communicate with modems.");
+ g_option_context_add_main_entries (opt_ctx, entries, NULL);
+
+ if (!g_option_context_parse (opt_ctx, &argc, &argv, &err)) {
+ g_warning ("%s\n", err->message);
+ g_error_free (err);
+ exit (1);
+ }
- if (!mm_options_debug ())
- logging_setup ();
+ g_option_context_free (opt_ctx);
+
+ if (debug) {
+ log_level = "DEBUG";
+ if (!show_ts && !rel_ts)
+ show_ts = TRUE;
+ }
+
+ if (!mm_log_setup (log_level, log_file, show_ts, rel_ts, &err)) {
+ g_warning ("Failed to set up logging: %s", err->message);
+ g_error_free (err);
+ exit (1);
+ }
+
+ setup_signals ();
- g_message ("ModemManager (version " MM_DIST_VERSION ") starting...");
+ mm_info ("ModemManager (version " MM_DIST_VERSION ") starting...");
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
if (!bus) {
@@ -235,7 +214,7 @@ main (int argc, char *argv[])
g_object_unref (proxy);
dbus_g_connection_unref (bus);
- logging_shutdown ();
+ mm_log_shutdown ();
return 0;
}
diff --git a/src/mm-at-serial-port.c b/src/mm-at-serial-port.c
index 3df8681b..30da3a3b 100644
--- a/src/mm-at-serial-port.c
+++ b/src/mm-at-serial-port.c
@@ -23,7 +23,7 @@
#include "mm-at-serial-port.h"
#include "mm-errors.h"
-#include "mm-options.h"
+#include "mm-log.h"
G_DEFINE_TYPE (MMAtSerialPort, mm_at_serial_port, MM_TYPE_SERIAL_PORT)
@@ -273,7 +273,6 @@ debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len)
{
static GString *debug = NULL;
const char *s;
- GTimeVal tv;
if (!debug)
debug = g_string_sized_new (256);
@@ -296,12 +295,7 @@ debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len)
}
g_string_append_c (debug, '\'');
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s): %s",
- tv.tv_sec,
- tv.tv_usec,
- mm_port_get_device (MM_PORT (port)),
- debug->str);
+ mm_dbg ("(%s): %s", mm_port_get_device (MM_PORT (port)), debug->str);
g_string_truncate (debug, 0);
}
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c
index f3e99d1a..0a95e7b1 100644
--- a/src/mm-generic-cdma.c
+++ b/src/mm-generic-cdma.c
@@ -30,6 +30,7 @@
#include "mm-serial-parsers.h"
#include "mm-modem-helpers.h"
#include "libqcdm/src/commands.h"
+#include "mm-log.h"
#define MM_GENERIC_CDMA_PREV_STATE_TAG "prev-state"
@@ -68,6 +69,8 @@ typedef struct {
guint poll_id;
+ char *meid;
+
MMModemCdmaRegistrationState cdma_1x_reg_state;
MMModemCdmaRegistrationState evdo_reg_state;
@@ -1045,7 +1048,7 @@ get_signal_quality (MMModemCdma *modem,
at_port = mm_generic_cdma_get_best_at_port (MM_GENERIC_CDMA (modem), &info->error);
if (!at_port && !priv->qcdm) {
- g_message ("Returning saved signal quality %d", priv->cdma1x_quality);
+ mm_dbg ("Returning saved signal quality %d", priv->cdma1x_quality);
mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->cdma1x_quality), NULL);
mm_callback_info_schedule (info);
return;
@@ -1524,15 +1527,22 @@ reg_query_speri_done (MMAtSerialPort *port,
if (!p || !mm_cdma_parse_eri (p, &roam, NULL, NULL))
goto done;
- /* Change the 1x and EVDO registration states to roaming if they were
- * anything other than UNKNOWN.
- */
if (roam) {
+ /* Change the 1x and EVDO registration states to roaming if they were
+ * anything other than UNKNOWN.
+ */
if (mm_generic_cdma_query_reg_state_get_callback_1x_state (info))
mm_generic_cdma_query_reg_state_set_callback_1x_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING);
if (mm_generic_cdma_query_reg_state_get_callback_evdo_state (info))
mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING);
+ } else {
+ /* Change 1x and/or EVDO registration state to home if home/roaming wasn't previously known */
+ if (mm_generic_cdma_query_reg_state_get_callback_1x_state (info) == MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED)
+ mm_generic_cdma_query_reg_state_set_callback_1x_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_HOME);
+
+ if (mm_generic_cdma_query_reg_state_get_callback_evdo_state (info) == MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED)
+ mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, MM_MODEM_CDMA_REGISTRATION_STATE_HOME);
}
done:
@@ -1584,6 +1594,12 @@ real_query_registration_state (MMGenericCdma *self,
port = mm_generic_cdma_get_best_at_port (self, &info->error);
if (!port) {
+ /* If we can't get an AT port, but less specific registration checks
+ * were successful, just use that and don't return an error.
+ */
+ if ( cur_cdma_state != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN
+ || cur_evdo_state != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)
+ g_clear_error (&info->error);
mm_callback_info_schedule (info);
return;
}
@@ -1722,7 +1738,7 @@ reg_hdrstate_cb (MMQcdmSerialPort *port,
/* Get HDR subsystem state to determine EVDO registration when in 1X mode */
result = qcdm_cmd_hdr_subsys_state_info_result ((const char *) response->data,
response->len,
- &info->error);
+ NULL);
if (result) {
guint8 session_state = QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_CLOSED;
guint8 almp_state = QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INACTIVE;
@@ -1801,19 +1817,24 @@ reg_cmstate_cb (MMQcdmSerialPort *port,
MMAtSerialPort *at_port = NULL;
QCDMResult *result = NULL;
guint32 opmode = 0, sysmode = 0;
+ GError *qcdm_error = NULL;
/* Parse the response */
if (!error)
- result = qcdm_cmd_cm_subsys_state_info_result ((const char *) response->data, response->len, &info->error);
+ result = qcdm_cmd_cm_subsys_state_info_result ((const char *) response->data, response->len, &qcdm_error);
if (!result) {
/* If there was some error, fall back to use +CAD like we did before QCDM */
if (info->modem)
at_port = mm_generic_cdma_get_best_at_port (MM_GENERIC_CDMA (info->modem), &info->error);
+ else
+ info->error = g_error_copy (qcdm_error);
+
if (at_port)
mm_at_serial_port_queue_command (at_port, "+CAD?", 3, get_analog_digital_done, info);
else
mm_callback_info_schedule (info);
+ g_clear_error (&qcdm_error);
return;
}
@@ -1856,8 +1877,8 @@ get_registration_state (MMModemCdma *modem,
port = mm_generic_cdma_get_best_at_port (MM_GENERIC_CDMA (modem), &info->error);
if (!port && !priv->qcdm) {
- g_message ("Returning saved registration states: 1x: %d EVDO: %d",
- priv->cdma_1x_reg_state, priv->evdo_reg_state);
+ mm_dbg ("Returning saved registration states: 1x: %d EVDO: %d",
+ priv->cdma_1x_reg_state, priv->evdo_reg_state);
mm_generic_cdma_query_reg_state_set_callback_1x_state (info, priv->cdma_1x_reg_state);
mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, priv->evdo_reg_state);
mm_callback_info_schedule (info);
@@ -2268,6 +2289,9 @@ get_property (GObject *object, guint prop_id,
case MM_MODEM_PROP_TYPE:
g_value_set_uint (value, MM_MODEM_TYPE_CDMA);
break;
+ case MM_MODEM_CDMA_PROP_MEID:
+ g_value_set_string (value, priv->meid);
+ break;
case PROP_EVDO_REV0:
g_value_set_boolean (value, priv->evdo_rev0);
break;
@@ -2320,6 +2344,10 @@ mm_generic_cdma_class_init (MMGenericCdmaClass *klass)
MM_MODEM_PROP_TYPE,
MM_MODEM_TYPE);
+ g_object_class_override_property (object_class,
+ MM_MODEM_CDMA_PROP_MEID,
+ MM_MODEM_CDMA_MEID);
+
g_object_class_install_property (object_class, PROP_EVDO_REV0,
g_param_spec_boolean (MM_GENERIC_CDMA_EVDO_REV0,
"EVDO rev0",
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 7f28dd5c..98713b0d 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -33,7 +33,7 @@
#include "mm-qcdm-serial-port.h"
#include "mm-serial-parsers.h"
#include "mm-modem-helpers.h"
-#include "mm-options.h"
+#include "mm-log.h"
#include "mm-properties-changed-signal.h"
#include "mm-utils.h"
#include "mm-modem-location.h"
@@ -471,10 +471,8 @@ get_iccid_done (MMModem *modem,
g_free (priv->simid);
priv->simid = g_strdup (g_checksum_get_string (sum));
- if (mm_options_debug ()) {
- g_debug ("SIM ID source '%s'", response);
- g_debug ("SIM ID '%s'", priv->simid);
- }
+ mm_dbg ("SIM ID source '%s'", response);
+ mm_dbg ("SIM ID '%s'", priv->simid);
g_object_notify (G_OBJECT (modem), MM_MODEM_GSM_CARD_SIM_IDENTIFIER);
@@ -990,6 +988,57 @@ periodic_poll_cb (gpointer user_data)
return TRUE; /* continue running */
}
+#define CREG_NUM_TAG "creg-num"
+#define CGREG_NUM_TAG "cgreg-num"
+
+static void
+initial_unsolicited_reg_check_done (MMCallbackInfo *info)
+{
+ MMGenericGsmPrivate *priv;
+ guint creg_num, cgreg_num;
+
+ if (!info->modem || info->error)
+ goto done;
+
+ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+ if (!priv->secondary)
+ goto done;
+
+ /* Enable unsolicited registration responses on secondary ports too,
+ * to ensure that we get the response even if the modem is connected
+ * on the primary port. We enable responses on both ports because we
+ * cannot trust modems to reliably send the responses on the port we
+ * enable them on.
+ */
+
+ creg_num = GPOINTER_TO_UINT (mm_callback_info_get_data (info, CREG_NUM_TAG));
+ switch (creg_num) {
+ case 1:
+ mm_at_serial_port_queue_command (priv->secondary, "+CREG=1", 3, NULL, NULL);
+ break;
+ case 2:
+ mm_at_serial_port_queue_command (priv->secondary, "+CREG=2", 3, NULL, NULL);
+ break;
+ default:
+ break;
+ }
+
+ cgreg_num = GPOINTER_TO_UINT (mm_callback_info_get_data (info, CGREG_NUM_TAG));
+ switch (cgreg_num) {
+ case 1:
+ mm_at_serial_port_queue_command (priv->secondary, "+CGREG=1", 3, NULL, NULL);
+ break;
+ case 2:
+ mm_at_serial_port_queue_command (priv->secondary, "+CGREG=2", 3, NULL, NULL);
+ break;
+ default:
+ break;
+ }
+
+done:
+ mm_callback_info_schedule (info);
+}
+
static void
cgreg1_done (MMAtSerialPort *port,
GString *response,
@@ -1007,11 +1056,14 @@ cgreg1_done (MMAtSerialPort *port,
/* The modem doesn't like unsolicited CGREG, so we'll need to poll */
priv->cgreg_poll = TRUE;
- }
+ } else
+ mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (1), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem);
}
- mm_callback_info_schedule (info);
+
+ initial_unsolicited_reg_check_done (info);
}
static void
@@ -1032,11 +1084,13 @@ cgreg2_done (MMAtSerialPort *port,
} else {
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
+ mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (2), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem);
/* All done */
- mm_callback_info_schedule (info);
+ initial_unsolicited_reg_check_done (info);
}
} else {
/* Modem got removed */
@@ -1061,7 +1115,9 @@ creg1_done (MMAtSerialPort *port,
/* The modem doesn't like unsolicited CREG, so we'll need to poll */
priv->creg_poll = TRUE;
- }
+ } else
+ mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (1), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem);
@@ -1090,6 +1146,8 @@ creg2_done (MMAtSerialPort *port,
} else {
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
+ mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (2), NULL);
+
/* Success; get initial state */
mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem);
@@ -1240,8 +1298,15 @@ cmer_cb (MMAtSerialPort *port,
GError *error,
gpointer user_data)
{
- if (!error)
- MM_GENERIC_GSM_GET_PRIVATE (user_data)->cmer_enabled = TRUE;
+ if (!error) {
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
+
+ priv->cmer_enabled = TRUE;
+
+ /* Enable CMER on the secondary port if we can too */
+ if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
+ mm_at_serial_port_queue_command (priv->secondary, "+CMER=3,0,0,1", 3, NULL, NULL);
+ }
}
static void
@@ -1306,12 +1371,9 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self,
*/
if (priv->secondary) {
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &error)) {
- if (mm_options_debug ()) {
- g_warning ("%s: error opening secondary port: (%d) %s",
- __func__,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- }
+ mm_dbg ("error opening secondary port: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
}
}
@@ -1524,11 +1586,16 @@ disable_flash_done (MMSerialPort *port,
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
/* Disable unsolicited messages */
- mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "AT+CREG=0", 3, NULL, NULL);
- mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "AT+CGREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "+CREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "+CGREG=0", 3, NULL, NULL);
if (priv->cmer_enabled) {
mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "+CMER=0", 3, NULL, NULL);
+
+ /* And on the secondary port */
+ if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
+ mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, NULL, NULL);
+
priv->cmer_enabled = FALSE;
}
@@ -1541,6 +1608,15 @@ disable_flash_done (MMSerialPort *port,
}
static void
+secondary_unsolicited_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ mm_serial_port_close_force (MM_SERIAL_PORT (port));
+}
+
+static void
disable (MMModem *modem,
MMModemFn callback,
gpointer user_data)
@@ -1575,9 +1651,12 @@ disable (MMModem *modem,
update_lac_ci (self, 0, 0, 1);
_internal_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
- /* Close the secondary port if its open */
- if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
- mm_serial_port_close_force (MM_SERIAL_PORT (priv->secondary));
+ /* Clean up the secondary port if it's open */
+ if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) {
+ mm_at_serial_port_queue_command (priv->secondary, "+CREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (priv->secondary, "+CGREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, secondary_unsolicited_done, NULL);
+ }
info = mm_callback_info_new (modem, callback, user_data);
@@ -2237,7 +2316,7 @@ roam_disconnect_done (MMModem *modem,
GError *error,
gpointer user_data)
{
- g_message ("Disconnected because roaming is not allowed");
+ mm_info ("Disconnected because roaming is not allowed");
}
static void
@@ -2268,9 +2347,9 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *self,
if (priv->reg_status[rs_type - 1] == status)
return;
- g_debug ("%s registration state changed: %d",
- (rs_type == MM_GENERIC_GSM_REG_TYPE_CS) ? "CS" : "PS",
- status);
+ mm_dbg ("%s registration state changed: %d",
+ (rs_type == MM_GENERIC_GSM_REG_TYPE_CS) ? "CS" : "PS",
+ status);
priv->reg_status[rs_type - 1] = status;
port = mm_generic_gsm_get_best_at_port (self, NULL);
@@ -2389,11 +2468,8 @@ reg_state_changed (MMAtSerialPort *port,
GError *error = NULL;
if (!mm_gsm_parse_creg_response (match_info, &state, &lac, &cell_id, &act, &cgreg, &error)) {
- if (mm_options_debug ()) {
- g_warning ("%s: error parsing unsolicited registration: %s",
- __func__,
- error && error->message ? error->message : "(unknown)");
- }
+ mm_warn ("error parsing unsolicited registration: %s",
+ error && error->message ? error->message : "(unknown)");
return;
}
@@ -3830,10 +3906,10 @@ ussd_update_state (MMGenericGsm *self, MMModemGsmUssdState new_state)
}
static void
-ussd_initiate_done (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
+ussd_send_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMGenericGsmPrivate *priv;
@@ -3860,10 +3936,7 @@ ussd_initiate_done (MMAtSerialPort *port,
case 0: /* no further action required */
ussd_state = MM_MODEM_GSM_USSD_STATE_IDLE;
break;
- case 1: /* Not an error but not yet implemented */
- info->error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Further action required.");
+ case 1: /* further action required */
ussd_state = MM_MODEM_GSM_USSD_STATE_USER_RESPONSE;
break;
case 2:
@@ -3894,10 +3967,8 @@ ussd_initiate_done (MMAtSerialPort *port,
if (reply) {
/* look for the reply data coding scheme */
- if (mm_options_debug ()) {
- if ((start = strrchr (end, ',')) != NULL)
- g_debug ("USSD data coding scheme %d", atoi (start + 1));
- }
+ if ((start = strrchr (end, ',')) != NULL)
+ mm_dbg ("USSD data coding scheme %d", atoi (start + 1));
converted = mm_modem_charset_hex_to_utf8 (reply, priv->cur_charset);
mm_callback_info_set_result (info, converted, g_free);
@@ -3919,10 +3990,10 @@ done:
}
static void
-ussd_initiate (MMModemGsmUssd *modem,
- const char *command,
- MMModemStringFn callback,
- gpointer user_data)
+ussd_send (MMModemGsmUssd *modem,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data)
{
MMCallbackInfo *info;
char *atc_command;
@@ -3947,13 +4018,57 @@ ussd_initiate (MMModemGsmUssd *modem,
atc_command = g_strdup_printf ("+CUSD=1,\"%s\",15", hex);
g_free (hex);
- mm_at_serial_port_queue_command (port, atc_command, 10, ussd_initiate_done, info);
+ mm_at_serial_port_queue_command (port, atc_command, 10, ussd_send_done, info);
g_free (atc_command);
ussd_update_state (MM_GENERIC_GSM (modem), MM_MODEM_GSM_USSD_STATE_ACTIVE);
}
static void
+ussd_initiate (MMModemGsmUssd *modem,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
+
+ if (priv->ussd_state != MM_MODEM_GSM_USSD_STATE_IDLE) {
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "USSD session already active.");
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ ussd_send (modem, command, callback, user_data);
+ return;
+}
+
+static void
+ussd_respond (MMModemGsmUssd *modem,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
+
+ if (priv->ussd_state != MM_MODEM_GSM_USSD_STATE_USER_RESPONSE) {
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "No active USSD session, cannot respond.");
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ ussd_send (modem, command, callback, user_data);
+ return;
+}
+
+static void
ussd_cancel_done (MMAtSerialPort *port,
GString *response,
GError *error,
@@ -4123,6 +4238,7 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data)
gboolean done = FALSE;
MMModemGsmAllowedMode allowed_mode;
gboolean home_only = FALSE;
+ char *data_device;
info->error = mm_modem_check_removed (modem, error);
if (info->error)
@@ -4130,16 +4246,9 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data)
priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
- if (mm_options_debug ()) {
- GTimeVal tv;
- char *data_device;
-
- g_object_get (G_OBJECT (modem), MM_MODEM_DATA_DEVICE, &data_device, NULL);
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s): simple connect state %d",
- tv.tv_sec, tv.tv_usec, data_device, state);
- g_free (data_device);
- }
+ g_object_get (G_OBJECT (modem), MM_MODEM_DATA_DEVICE, &data_device, NULL);
+ mm_dbg ("(%s): simple connect state %d", data_device, state);
+ g_free (data_device);
switch (state) {
case SIMPLE_STATE_CHECK_PIN:
@@ -4238,29 +4347,21 @@ simple_connect (MMModemSimple *simple,
gpointer user_data)
{
MMCallbackInfo *info;
+ GHashTableIter iter;
+ gpointer key, value;
+ char *data_device;
- /* If debugging, list all the simple connect properties */
- if (mm_options_debug ()) {
- GHashTableIter iter;
- gpointer key, value;
- GTimeVal tv;
- char *data_device;
-
- g_object_get (G_OBJECT (simple), MM_MODEM_DATA_DEVICE, &data_device, NULL);
- g_get_current_time (&tv);
-
- g_hash_table_iter_init (&iter, properties);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- char *val_str;
-
- val_str = g_strdup_value_contents ((GValue *) value);
- g_debug ("<%ld.%ld> (%s): %s => %s",
- tv.tv_sec, tv.tv_usec,
- data_device, (const char *) key, val_str);
- g_free (val_str);
- }
- g_free (data_device);
+ /* List simple connect properties when debugging */
+ g_object_get (G_OBJECT (simple), MM_MODEM_DATA_DEVICE, &data_device, NULL);
+ g_hash_table_iter_init (&iter, properties);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ char *val_str;
+
+ val_str = g_strdup_value_contents ((GValue *) value);
+ mm_dbg ("(%s): %s => %s", data_device, (const char *) key, val_str);
+ g_free (val_str);
}
+ g_free (data_device);
info = mm_callback_info_new (MM_MODEM (simple), callback, user_data);
mm_callback_info_set_data (info, "simple-connect-properties",
@@ -4633,6 +4734,7 @@ static void
modem_gsm_ussd_init (MMModemGsmUssd *class)
{
class->initiate = ussd_initiate;
+ class->respond = ussd_respond;
class->cancel = ussd_cancel;
}
diff --git a/src/mm-log.c b/src/mm-log.c
new file mode 100644
index 00000000..82d40bc8
--- /dev/null
+++ b/src/mm-log.c
@@ -0,0 +1,227 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mm-log.h"
+
+enum {
+ TS_FLAG_NONE = 0,
+ TS_FLAG_WALL,
+ TS_FLAG_REL
+};
+
+static gboolean ts_flags = TS_FLAG_NONE;
+static guint32 log_level = LOGL_INFO | LOGL_WARN | LOGL_ERR;
+static GTimeVal rel_start = { 0, 0 };
+static int logfd = -1;
+
+typedef struct {
+ guint32 num;
+ const char *name;
+} LogDesc;
+
+static const LogDesc level_descs[] = {
+ { LOGL_ERR, "ERR" },
+ { LOGL_WARN | LOGL_ERR, "WARN" },
+ { LOGL_INFO | LOGL_WARN | LOGL_ERR, "INFO" },
+ { LOGL_DEBUG | LOGL_INFO | LOGL_WARN | LOGL_ERR, "DEBUG" },
+ { 0, NULL }
+};
+
+void
+_mm_log (const char *loc,
+ const char *func,
+ guint32 level,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+ char *msg;
+ GTimeVal tv;
+ char tsbuf[100] = { 0 };
+ char msgbuf[512] = { 0 };
+ int syslog_priority = LOG_INFO;
+ const char *prefix = NULL;
+
+ if (!(log_level & level))
+ return;
+
+ va_start (args, fmt);
+ msg = g_strdup_vprintf (fmt, args);
+ va_end (args);
+
+ if (ts_flags == TS_FLAG_WALL) {
+ g_get_current_time (&tv);
+ snprintf (&tsbuf[0], sizeof (tsbuf), " [%09ld.%06ld]", tv.tv_sec, tv.tv_usec);
+ } else if (ts_flags == TS_FLAG_REL) {
+ time_t secs;
+ suseconds_t usecs;
+
+ g_get_current_time (&tv);
+ secs = tv.tv_sec - rel_start.tv_sec;
+ usecs = tv.tv_usec - rel_start.tv_usec;
+ if (usecs < 0) {
+ secs--;
+ usecs += 1000000;
+ }
+
+ snprintf (&tsbuf[0], sizeof (tsbuf), " [%06ld.%06ld]", secs, usecs);
+ }
+
+ if ((log_level & LOGL_DEBUG) && (level == LOGL_DEBUG))
+ prefix = "debug";
+ else if ((log_level & LOGL_INFO) && (level == LOGL_INFO))
+ prefix = "info";
+ else if ((log_level & LOGL_WARN) && (level == LOGL_WARN)) {
+ prefix = "warn";
+ syslog_priority = LOG_WARNING;
+ } else if ((log_level & LOGL_ERR) && (level == LOGL_ERR)) {
+ prefix = "err";
+ syslog_priority = LOG_ERR;
+ } else
+ g_warn_if_reached ();
+
+ if (prefix) {
+ if (log_level & LOGL_DEBUG)
+ snprintf (msgbuf, sizeof (msgbuf), "<%s>%s [%s] %s(): %s\n", prefix, tsbuf, loc, func, msg);
+ else
+ snprintf (msgbuf, sizeof (msgbuf), "<%s>%s %s\n", prefix, tsbuf, msg);
+
+ if (logfd < 0)
+ syslog (syslog_priority, "%s", msgbuf);
+ else {
+ write (logfd, msgbuf, strlen (msgbuf));
+ fsync (logfd); /* Make sure output is dumped to disk immediately */
+ }
+ }
+
+ g_free (msg);
+}
+
+static void
+log_handler (const gchar *log_domain,
+ GLogLevelFlags level,
+ const gchar *message,
+ gpointer ignored)
+{
+ int syslog_priority;
+
+ switch (level) {
+ case G_LOG_LEVEL_ERROR:
+ syslog_priority = LOG_CRIT;
+ break;
+ case G_LOG_LEVEL_CRITICAL:
+ syslog_priority = LOG_ERR;
+ break;
+ case G_LOG_LEVEL_WARNING:
+ syslog_priority = LOG_WARNING;
+ break;
+ case G_LOG_LEVEL_MESSAGE:
+ syslog_priority = LOG_NOTICE;
+ break;
+ case G_LOG_LEVEL_DEBUG:
+ syslog_priority = LOG_DEBUG;
+ break;
+ case G_LOG_LEVEL_INFO:
+ default:
+ syslog_priority = LOG_INFO;
+ break;
+ }
+
+ if (logfd < 0)
+ syslog (syslog_priority, "%s", message);
+ else
+ write (logfd, message, strlen (message));
+}
+
+gboolean
+mm_log_setup (const char *level,
+ const char *log_file,
+ gboolean show_timestamps,
+ gboolean rel_timestamps,
+ GError **error)
+{
+ /* levels */
+ if (level && strlen (level)) {
+ gboolean found = FALSE;
+ const LogDesc *diter;
+
+ for (diter = &level_descs[0]; diter->name; diter++) {
+ if (!strcasecmp (diter->name, level)) {
+ log_level = diter->num;
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ g_set_error (error, 0, 0, "Unknown log level '%s'", level);
+ return FALSE;
+ }
+ }
+
+ if (show_timestamps)
+ ts_flags = TS_FLAG_WALL;
+ else if (rel_timestamps)
+ ts_flags = TS_FLAG_REL;
+
+ /* Grab start time for relative timestamps */
+ g_get_current_time (&rel_start);
+
+ if (log_file == NULL)
+ openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PID | LOG_PERROR, LOG_DAEMON);
+ else {
+ logfd = open (log_file,
+ O_CREAT | O_APPEND | O_WRONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (logfd < 0) {
+ g_set_error (error, 0, 0, "Failed to open log file: (%d) %s",
+ errno, strerror (errno));
+ return FALSE;
+ }
+ }
+
+ g_log_set_handler (G_LOG_DOMAIN,
+ G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
+ log_handler,
+ NULL);
+
+ return TRUE;
+}
+
+void
+mm_log_usr1 (void)
+{
+}
+
+void
+mm_log_shutdown (void)
+{
+ if (logfd < 0)
+ closelog ();
+ else
+ close (logfd);
+}
+
diff --git a/src/mm-log.h b/src/mm-log.h
new file mode 100644
index 00000000..9b0d875f
--- /dev/null
+++ b/src/mm-log.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ */
+
+#ifndef MM_LOG_H
+#define MM_LOG_H
+
+#include <glib.h>
+
+/* Log levels */
+enum {
+ LOGL_ERR = 0x00000001,
+ LOGL_WARN = 0x00000002,
+ LOGL_INFO = 0x00000004,
+ LOGL_DEBUG = 0x00000008
+};
+
+#define mm_err(...) \
+ _mm_log (G_STRLOC, G_STRFUNC, LOGL_ERR, ## __VA_ARGS__ )
+
+#define mm_warn(...) \
+ _mm_log (G_STRLOC, G_STRFUNC, LOGL_WARN, ## __VA_ARGS__ )
+
+#define mm_info(...) \
+ _mm_log (G_STRLOC, G_STRFUNC, LOGL_INFO, ## __VA_ARGS__ )
+
+#define mm_dbg(...) \
+ _mm_log (G_STRLOC, G_STRFUNC, LOGL_DEBUG, ## __VA_ARGS__ )
+
+#define mm_log(level, ...) \
+ _mm_log (G_STRLOC, G_STRFUNC, level, ## __VA_ARGS__ )
+
+void _mm_log (const char *loc,
+ const char *func,
+ guint32 level,
+ const char *fmt,
+ ...) __attribute__((__format__ (__printf__, 4, 5)));
+
+gboolean mm_log_setup (const char *level,
+ const char *log_file,
+ gboolean show_ts,
+ gboolean rel_ts,
+ GError **error);
+
+void mm_log_usr1 (void);
+
+void mm_log_shutdown (void);
+
+#endif /* MM_LOG_H */
+
diff --git a/src/mm-manager.c b/src/mm-manager.c
index 605ec5a1..561d427c 100644
--- a/src/mm-manager.c
+++ b/src/mm-manager.c
@@ -24,6 +24,7 @@
#include "mm-manager.h"
#include "mm-errors.h"
#include "mm-plugin.h"
+#include "mm-log.h"
static gboolean impl_manager_enumerate_devices (MMManager *manager,
GPtrArray **devices,
@@ -112,9 +113,9 @@ load_plugin (const char *path)
plugin = (*plugin_create_func) ();
if (plugin) {
g_object_weak_ref (G_OBJECT (plugin), (GWeakNotify) g_module_close, module);
- g_message ("Loaded plugin %s", mm_plugin_get_name (plugin));
+ mm_info ("Loaded plugin %s", mm_plugin_get_name (plugin));
} else
- g_warning ("Could not load plugin %s: initialization failed", path);
+ mm_warn ("Could not load plugin %s: initialization failed", path);
out:
if (!plugin)
@@ -196,7 +197,7 @@ remove_modem (MMManager *manager, MMModem *modem)
device = mm_modem_get_device (modem);
g_assert (device);
- g_debug ("Removed modem %s", device);
+ mm_dbg ("Removed modem %s", device);
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
g_hash_table_remove (priv->modems, device);
@@ -234,8 +235,8 @@ check_export_modem (MMManager *self, MMModem *modem)
SupportsInfo *info = value;
if (!strcmp (info->physdev_path, modem_physdev)) {
- g_debug ("(%s/%s): outstanding support task prevents export of %s",
- info->subsys, info->name, modem_physdev);
+ mm_dbg ("(%s/%s): outstanding support task prevents export of %s",
+ info->subsys, info->name, modem_physdev);
goto out;
}
}
@@ -257,7 +258,7 @@ check_export_modem (MMManager *self, MMModem *modem)
dbus_g_connection_register_g_object (priv->connection, path, G_OBJECT (modem));
g_object_set_data_full (G_OBJECT (modem), DBUS_PATH_TAG, path, (GDestroyNotify) g_free);
- g_debug ("Exported modem %s as %s", modem_physdev, path);
+ mm_dbg ("Exported modem %s as %s", modem_physdev, path);
physdev = g_udev_client_query_by_sysfs_path (priv->udev, modem_physdev);
if (physdev)
@@ -268,10 +269,10 @@ check_export_modem (MMManager *self, MMModem *modem)
MM_MODEM_HW_VID, &vid,
MM_MODEM_HW_PID, &pid,
NULL);
- g_debug ("(%s): VID 0x%04X PID 0x%04X (%s)",
+ mm_dbg ("(%s): VID 0x%04X PID 0x%04X (%s)",
path, (vid & 0xFFFF), (pid & 0xFFFF),
subsys ? subsys : "unknown");
- g_debug ("(%s): data port is %s", path, data_device);
+ mm_dbg ("(%s): data port is %s", path, data_device);
g_free (data_device);
if (physdev)
@@ -309,7 +310,7 @@ add_modem (MMManager *manager, MMModem *modem, MMPlugin *plugin)
g_hash_table_insert (priv->modems, g_strdup (device), modem);
g_object_set_data (G_OBJECT (modem), MANAGER_PLUGIN_TAG, plugin);
- g_debug ("Added modem %s", device);
+ mm_dbg ("Added modem %s", device);
g_signal_connect (modem, "notify::" MM_MODEM_VALID, G_CALLBACK (modem_valid), manager);
check_export_modem (manager, modem);
}
@@ -446,7 +447,7 @@ supports_defer_timeout (gpointer user_data)
existing = find_modem_for_device (info->manager, info->physdev_path);
- g_debug ("(%s): re-checking support...", info->name);
+ mm_dbg ("(%s): re-checking support...", info->name);
try_supports_port (info->manager,
MM_PLUGIN (info->cur_plugin->data),
existing,
@@ -478,9 +479,9 @@ try_supports_port (MMManager *manager,
supports_callback (plugin, info->subsys, info->name, 0, info);
break;
case MM_PLUGIN_SUPPORTS_PORT_DEFER:
- g_debug ("(%s): (%s) deferring support check",
- mm_plugin_get_name (plugin),
- info->name);
+ mm_dbg ("(%s): (%s) deferring support check",
+ mm_plugin_get_name (plugin),
+ info->name);
if (info->defer_id)
g_source_remove (info->defer_id);
@@ -549,22 +550,21 @@ do_grab_port (gpointer user_data)
type_name = "CDMA";
device = mm_modem_get_device (modem);
- g_message ("(%s): %s modem %s claimed port %s",
- mm_plugin_get_name (info->best_plugin),
- type_name,
- device,
- info->name);
+ mm_info ("(%s): %s modem %s claimed port %s",
+ mm_plugin_get_name (info->best_plugin),
+ type_name,
+ device,
+ info->name);
g_free (device);
add_modem (info->manager, modem, info->best_plugin);
} else {
- g_warning ("%s: plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
- __func__,
- mm_plugin_get_name (info->best_plugin),
- info->subsys,
- info->name,
- error ? error->code : -1,
- (error && error->message) ? error->message : "(unknown)");
+ mm_warn ("plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
+ mm_plugin_get_name (info->best_plugin),
+ info->subsys,
+ info->name,
+ error ? error->code : -1,
+ (error && error->message) ? error->message : "(unknown)");
modem = existing;
}
}
@@ -613,8 +613,8 @@ supports_callback (MMPlugin *plugin,
* support this port, but this plugin is clearly the right plugin
* since it claimed this port's physical modem, just drop the port.
*/
- g_debug ("(%s/%s): ignoring port unsupported by physical modem's plugin",
- info->subsys, info->name);
+ mm_dbg ("(%s/%s): ignoring port unsupported by physical modem's plugin",
+ info->subsys, info->name);
supports_cleanup (info->manager, info->subsys, info->name, existing);
return;
}
@@ -631,14 +631,14 @@ supports_callback (MMPlugin *plugin,
*/
next_plugin = existing_plugin;
} else {
- g_debug ("(%s/%s): plugin %p (%s) existing %p (%s) info->best %p (%s)",
- info->subsys, info->name,
- plugin,
- plugin ? mm_plugin_get_name (plugin) : "none",
- existing_plugin,
- existing_plugin ? mm_plugin_get_name (existing_plugin) : "none",
- info->best_plugin,
- info->best_plugin ? mm_plugin_get_name (info->best_plugin) : "none");
+ mm_dbg ("(%s/%s): plugin %p (%s) existing %p (%s) info->best %p (%s)",
+ info->subsys, info->name,
+ plugin,
+ plugin ? mm_plugin_get_name (plugin) : "none",
+ existing_plugin,
+ existing_plugin ? mm_plugin_get_name (existing_plugin) : "none",
+ info->best_plugin,
+ info->best_plugin ? mm_plugin_get_name (info->best_plugin) : "none");
g_assert_not_reached ();
}
} else {
@@ -783,14 +783,14 @@ device_added (MMManager *manager, GUdevDevice *device)
&& strcmp (name, "lo")
&& strcmp (name, "tty")
&& !strstr (name, "virbr"))
- g_debug ("(%s/%s): could not get port's parent device", subsys, name);
+ mm_dbg ("(%s/%s): could not get port's parent device", subsys, name);
goto out;
}
/* Is the device blacklisted? */
if (g_udev_device_get_property_as_boolean (physdev, "ID_MM_DEVICE_IGNORE")) {
- g_debug ("(%s/%s): port's parent device is blacklisted", subsys, name);
+ mm_dbg ("(%s/%s): port's parent device is blacklisted", subsys, name);
goto out;
}
@@ -799,13 +799,13 @@ device_added (MMManager *manager, GUdevDevice *device)
if ( physdev_subsys
&& !strcmp (physdev_subsys, "platform")
&& !g_udev_device_get_property_as_boolean (physdev, "ID_MM_PLATFORM_DRIVER_PROBE")) {
- g_debug ("(%s/%s): port's parent platform driver is not whitelisted", subsys, name);
+ mm_dbg ("(%s/%s): port's parent platform driver is not whitelisted", subsys, name);
goto out;
}
physdev_path = g_udev_device_get_sysfs_path (physdev);
if (!physdev_path) {
- g_debug ("(%s/%s): could not get port's parent device sysfs path", subsys, name);
+ mm_dbg ("(%s/%s): could not get port's parent device sysfs path", subsys, name);
goto out;
}
@@ -836,7 +836,7 @@ device_removed (MMManager *manager, GUdevDevice *device)
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
MMModem *modem;
const char *subsys, *name;
- char *key;
+ char *key, *modem_device;
SupportsInfo *info;
g_return_if_fail (device != NULL);
@@ -851,6 +851,9 @@ device_removed (MMManager *manager, GUdevDevice *device)
/* find_modem_for_port handles tty and net removal */
modem = find_modem_for_port (manager, subsys, name);
if (modem) {
+ modem_device = mm_modem_get_device (modem);
+ mm_info ("(%s/%s): released by modem %s", subsys, name, modem_device);
+ g_free (modem_device);
mm_modem_release_port (modem, subsys, name);
return;
}
@@ -865,10 +868,9 @@ device_removed (MMManager *manager, GUdevDevice *device)
*/
const char *sysfs_path = g_udev_device_get_sysfs_path (device);
- // g_debug ("Looking for a modem for removed device %s", sysfs_path);
modem = find_modem_for_device (manager, sysfs_path);
if (modem) {
- g_debug ("Removing modem claimed by removed device %s", sysfs_path);
+ mm_dbg ("Removing modem claimed by removed device %s", sysfs_path);
remove_modem (manager, modem);
return;
}
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index 50088fb5..ee5e1c86 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -25,7 +25,7 @@
#include "mm-at-serial-port.h"
#include "mm-qcdm-serial-port.h"
#include "mm-errors.h"
-#include "mm-options.h"
+#include "mm-log.h"
#include "mm-properties-changed-signal.h"
#include "mm-callback-info.h"
#include "mm-modem-helpers.h"
@@ -148,15 +148,13 @@ mm_modem_base_add_port (MMModemBase *self,
if (!port)
return NULL;
- if (mm_options_debug ()) {
- device = mm_modem_get_device (MM_MODEM (self));
+ device = mm_modem_get_device (MM_MODEM (self));
+ mm_dbg ("(%s) type %s claimed by %s",
+ name,
+ mm_port_type_to_name (ptype),
+ device);
+ g_free (device);
- g_message ("(%s) type %s claimed by %s",
- name,
- mm_port_type_to_name (ptype),
- device);
- g_free (device);
- }
key = get_hash_key (subsys, name);
g_hash_table_insert (priv->ports, key, port);
return port;
@@ -165,10 +163,32 @@ mm_modem_base_add_port (MMModemBase *self,
gboolean
mm_modem_base_remove_port (MMModemBase *self, MMPort *port)
{
+ MMModemBasePrivate *priv;
+ char *device, *key, *name;
+ const char *type_name, *subsys;
+ gboolean removed;
+
g_return_val_if_fail (MM_IS_MODEM_BASE (self), FALSE);
g_return_val_if_fail (port != NULL, FALSE);
- return g_hash_table_remove (MM_MODEM_BASE_GET_PRIVATE (self)->ports, port);
+ priv = MM_MODEM_BASE_GET_PRIVATE (self);
+
+ name = g_strdup (mm_port_get_device (port));
+ subsys = mm_port_subsys_to_name (mm_port_get_subsys (port));
+ type_name = mm_port_type_to_name (mm_port_get_port_type (port));
+
+ key = get_hash_key (subsys, name);
+ removed = g_hash_table_remove (priv->ports, key);
+ if (removed) {
+ /* Port may have already been destroyed by removal from the hash */
+ device = mm_modem_get_device (MM_MODEM (self));
+ mm_dbg ("(%s) type %s removed from %s", name, type_name, device);
+ g_free (device);
+ }
+ g_free (key);
+ g_free (name);
+
+ return removed;
}
void
@@ -233,9 +253,9 @@ mm_modem_base_set_equipment_identifier (MMModemBase *self, const char *ident)
dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
if (dbus_path) {
if (priv->equipment_ident)
- g_message ("Modem %s: Equipment identifier set (%s)", dbus_path, priv->equipment_ident);
+ mm_info ("Modem %s: Equipment identifier set (%s)", dbus_path, priv->equipment_ident);
else
- g_message ("Modem %s: Equipment identifier not set", dbus_path);
+ mm_warn ("Modem %s: Equipment identifier not set", dbus_path);
}
g_object_notify (G_OBJECT (self), MM_MODEM_EQUIPMENT_IDENTIFIER);
@@ -274,9 +294,9 @@ mm_modem_base_set_unlock_required (MMModemBase *self, const char *unlock_require
dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
if (dbus_path) {
if (priv->unlock_required)
- g_message ("Modem %s: unlock required (%s)", dbus_path, priv->unlock_required);
+ mm_info ("Modem %s: unlock required (%s)", dbus_path, priv->unlock_required);
else
- g_message ("Modem %s: unlock no longer required", dbus_path);
+ mm_info ("Modem %s: unlock no longer required", dbus_path);
}
g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_REQUIRED);
@@ -311,11 +331,11 @@ mm_modem_base_set_unlock_retries (MMModemBase *self, guint unlock_retries)
dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
if (dbus_path) {
if (priv->unlock_required) {
- g_message ("Modem %s: # unlock retries for %s is %d",
- dbus_path, priv->unlock_required, priv->unlock_retries);
+ mm_info ("Modem %s: # unlock retries for %s is %d",
+ dbus_path, priv->unlock_required, priv->unlock_retries);
} else {
- g_message ("Modem %s: # unlock retries is %d",
- dbus_path, priv->unlock_retries);
+ mm_info ("Modem %s: # unlock retries is %d",
+ dbus_path, priv->unlock_retries);
}
}
@@ -446,8 +466,7 @@ card_info_cache_invoke (MMCallbackInfo *info)
priv->gsn,
priv->revision,
priv->model,
- priv->manf,
- mm_options_debug ());
+ priv->manf);
g_object_notify (G_OBJECT (self), MM_MODEM_DEVICE_IDENTIFIER);
callback (info->modem, priv->manf, priv->model, priv->revision, info->error, info->user_data);
@@ -626,6 +645,10 @@ mm_modem_base_init (MMModemBase *self)
MM_MODEM_UNLOCK_RETRIES,
NULL,
MM_MODEM_DBUS_INTERFACE);
+ mm_properties_changed_signal_register_property (G_OBJECT (self),
+ MM_MODEM_IP_METHOD,
+ NULL,
+ MM_MODEM_DBUS_INTERFACE);
}
static void
diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c
index 3f4ffe54..722918e0 100644
--- a/src/mm-modem-cdma.c
+++ b/src/mm-modem-cdma.c
@@ -357,6 +357,15 @@ mm_modem_cdma_init (gpointer g_iface)
if (initialized)
return;
+ /* Properties */
+ g_object_interface_install_property
+ (g_iface,
+ g_param_spec_string (MM_MODEM_CDMA_MEID,
+ "MEID",
+ "MEID",
+ NULL,
+ G_PARAM_READABLE));
+
/* Signals */
signals[SIGNAL_QUALITY] =
g_signal_new ("signal-quality",
diff --git a/src/mm-modem-cdma.h b/src/mm-modem-cdma.h
index 89751518..4d30386a 100644
--- a/src/mm-modem-cdma.h
+++ b/src/mm-modem-cdma.h
@@ -35,6 +35,14 @@ typedef enum {
#define MM_MODEM_CDMA_REGISTRATION_STATE_CHANGED "registration-state-changed"
+#define MM_MODEM_CDMA_MEID "meid"
+
+typedef enum {
+ MM_MODEM_CDMA_PROP_FIRST = 0x1200,
+
+ MM_MODEM_CDMA_PROP_MEID = MM_MODEM_CDMA_PROP_FIRST,
+} MMModemCdmaProp;
+
typedef struct _MMModemCdma MMModemCdma;
typedef void (*MMModemCdmaServingSystemFn) (MMModemCdma *modem,
diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c
index 4cd69218..75ca7de9 100644
--- a/src/mm-modem-gsm-network.c
+++ b/src/mm-modem-gsm-network.c
@@ -108,6 +108,8 @@ mm_modem_gsm_network_act_to_old_mode (MMModemGsmAccessTech act)
return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA;
else if (act & MM_MODEM_GSM_ACCESS_TECH_HSPA)
return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA;
+ else if (act & MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS)
+ return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA;
return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY;
}
diff --git a/src/mm-modem-gsm-ussd.c b/src/mm-modem-gsm-ussd.c
index def22134..f90a8458 100644
--- a/src/mm-modem-gsm-ussd.c
+++ b/src/mm-modem-gsm-ussd.c
@@ -106,6 +106,23 @@ mm_modem_gsm_ussd_initiate (MMModemGsmUssd *self,
}
void
+mm_modem_gsm_ussd_respond (MMModemGsmUssd *self,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM_GSM_USSD (self));
+ g_return_if_fail (command != NULL);
+ g_return_if_fail (callback != NULL);
+
+ if (MM_MODEM_GSM_USSD_GET_INTERFACE (self)->respond)
+ MM_MODEM_GSM_USSD_GET_INTERFACE (self)->respond(self, command, callback, user_data);
+ else
+ str_call_not_supported (self, callback, user_data);
+
+}
+
+void
mm_modem_gsm_ussd_cancel (MMModemGsmUssd *self,
MMModemFn callback,
gpointer user_data)
@@ -149,16 +166,6 @@ ussd_auth_info_new (const char* command)
/*****************************************************************************/
static void
-impl_modem_gsm_ussd_respond (MMModemGsmUssd *modem,
- const char *responste,
- DBusGMethodInvocation *context)
-{
- async_call_not_supported (modem, async_call_done, context);
-}
-
-/*****************************************************************************/
-
-static void
ussd_initiate_auth_cb (MMAuthRequest *req,
GObject *owner,
DBusGMethodInvocation *context,
@@ -209,6 +216,56 @@ impl_modem_gsm_ussd_initiate (MMModemGsmUssd *modem,
}
static void
+ussd_respond_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmUssd *self = MM_MODEM_GSM_USSD (owner);
+ UssdAuthInfo *info = user_data;
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise respond to the USSD */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error))
+ goto done;
+
+ if (!info->command) {
+ error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Missing USSD command");
+ }
+
+done:
+ if (error) {
+ str_call_done (MM_MODEM (self), NULL, error, context);
+ g_error_free (error);
+ } else
+ mm_modem_gsm_ussd_respond (self, info->command, str_call_done, context);
+}
+
+static void
+impl_modem_gsm_ussd_respond (MMModemGsmUssd *modem,
+ const char *command,
+ DBusGMethodInvocation *context)
+{
+ GError *error = NULL;
+ UssdAuthInfo *info;
+
+ info = ussd_auth_info_new (command);
+
+ /* Make sure the caller is authorized to respond to the USSD */
+ if (!mm_modem_auth_request (MM_MODEM (modem),
+ MM_AUTHORIZATION_USSD,
+ context,
+ ussd_respond_auth_cb,
+ info,
+ ussd_auth_info_destroy,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+static void
ussd_cancel_auth_cb (MMAuthRequest *req,
GObject *owner,
DBusGMethodInvocation *context,
diff --git a/src/mm-modem-gsm-ussd.h b/src/mm-modem-gsm-ussd.h
index d0da59be..c8f652b9 100644
--- a/src/mm-modem-gsm-ussd.h
+++ b/src/mm-modem-gsm-ussd.h
@@ -46,6 +46,11 @@ struct _MMModemGsmUssd {
MMModemStringFn callback,
gpointer user_data);
+ void (*respond) (MMModemGsmUssd *modem,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data);
+
void (*cancel) (MMModemGsmUssd *modem,
MMModemFn callback,
gpointer user_data);
@@ -58,6 +63,11 @@ void mm_modem_gsm_ussd_initiate (MMModemGsmUssd *self,
MMModemStringFn callback,
gpointer user_data);
+void mm_modem_gsm_ussd_respond (MMModemGsmUssd *self,
+ const char *command,
+ MMModemStringFn callback,
+ gpointer user_data);
+
void mm_modem_gsm_ussd_cancel (MMModemGsmUssd *self,
MMModemFn callback,
gpointer user_data);
diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h
index 6d9135a4..a427d354 100644
--- a/src/mm-modem-gsm.h
+++ b/src/mm-modem-gsm.h
@@ -54,8 +54,9 @@ typedef enum {
MM_MODEM_GSM_ACCESS_TECH_HSDPA = 6, /* UTRAN w/HSDPA */
MM_MODEM_GSM_ACCESS_TECH_HSUPA = 7, /* UTRAN w/HSUPA */
MM_MODEM_GSM_ACCESS_TECH_HSPA = 8, /* UTRAN w/HSDPA and HSUPA */
+ MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS = 9, /* UTRAN w/HSPA+ */
- MM_MODEM_GSM_ACCESS_TECH_LAST = MM_MODEM_GSM_ACCESS_TECH_HSPA
+ MM_MODEM_GSM_ACCESS_TECH_LAST = MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS
} MMModemGsmAccessTech;
typedef enum {
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 25998b1f..f13b4f27 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -25,6 +25,7 @@
#include "mm-errors.h"
#include "mm-modem-helpers.h"
+#include "mm-log.h"
const char *
mm_strip_tag (const char *str, const char *cmd)
@@ -242,10 +243,14 @@ mm_gsm_destroy_scan_data (gpointer data)
/* +CREG: <n>,<stat>,<lac>,<ci>,<AcT> (ETSI 27.007 solicited and some CREG=2 unsolicited) */
#define CREG6 "\\+(CREG|CGREG):\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})"
+/* +CREG: <n>,<stat>,<lac>,<ci>,<AcT?>,<something> (Samsung Wave S8500) */
+/* '<CR><LF>+CREG: 2,1,000B,2816, B, C2816<CR><LF><CR><LF>OK<CR><LF>' */
+#define CREG7 "\\+(CREG|CGREG):\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*[^,\\s]*"
+
GPtrArray *
mm_gsm_creg_regex_get (gboolean solicited)
{
- GPtrArray *array = g_ptr_array_sized_new (6);
+ GPtrArray *array = g_ptr_array_sized_new (7);
GRegex *regex;
/* #1 */
@@ -296,6 +301,14 @@ mm_gsm_creg_regex_get (gboolean solicited)
g_assert (regex);
g_ptr_array_add (array, regex);
+ /* #7 */
+ if (solicited)
+ regex = g_regex_new (CREG7 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ else
+ regex = g_regex_new ("\\r\\n" CREG7 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ g_assert (regex);
+ g_ptr_array_add (array, regex);
+
return array;
}
@@ -785,7 +798,9 @@ mm_gsm_string_to_access_tech (const char *string)
/* Better technologies are listed first since modems sometimes say
* stuff like "GPRS/EDGE" and that should be handled as EDGE.
*/
- if (strcasestr (string, "HSPA"))
+ if (strcasestr (string, "HSPA+"))
+ return MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS;
+ else if (strcasestr (string, "HSPA"))
return MM_MODEM_GSM_ACCESS_TECH_HSPA;
else if (strcasestr (string, "HSDPA/HSUPA"))
return MM_MODEM_GSM_ACCESS_TECH_HSPA;
@@ -815,10 +830,9 @@ mm_create_device_identifier (guint vid,
const char *gsn,
const char *revision,
const char *model,
- const char *manf,
- gboolean debug)
+ const char *manf)
{
- GString *devid, *dbg = NULL;
+ GString *devid, *msg = NULL;
GChecksum *sum;
char *p, *ret = NULL;
char str_vid[10], str_pid[10];
@@ -845,41 +859,35 @@ mm_create_device_identifier (guint vid,
return NULL;
p = devid->str;
- if (debug)
- dbg = g_string_sized_new (strlen (devid->str) + 17);
+ msg = g_string_sized_new (strlen (devid->str) + 17);
sum = g_checksum_new (G_CHECKSUM_SHA1);
if (vid) {
snprintf (str_vid, sizeof (str_vid) - 1, "%08x", vid);
g_checksum_update (sum, (const guchar *) &str_vid[0], strlen (str_vid));
- if (dbg)
- g_string_append_printf (dbg, "%08x", vid);
+ g_string_append_printf (msg, "%08x", vid);
}
if (vid) {
snprintf (str_pid, sizeof (str_pid) - 1, "%08x", pid);
g_checksum_update (sum, (const guchar *) &str_pid[0], strlen (str_pid));
- if (dbg)
- g_string_append_printf (dbg, "%08x", pid);
+ g_string_append_printf (msg, "%08x", pid);
}
while (*p) {
/* Strip spaces and linebreaks */
if (!isblank (*p) && !isspace (*p) && isascii (*p)) {
g_checksum_update (sum, (const guchar *) p, 1);
- if (dbg)
- g_string_append_c (dbg, *p);
+ g_string_append_c (msg, *p);
}
p++;
}
ret = g_strdup (g_checksum_get_string (sum));
g_checksum_free (sum);
- if (dbg) {
- g_debug ("Device ID source '%s'", dbg->str);
- g_debug ("Device ID '%s'", ret);
- g_string_free (dbg, TRUE);
- }
+ mm_dbg ("Device ID source '%s'", msg->str);
+ mm_dbg ("Device ID '%s'", ret);
+ g_string_free (msg, TRUE);
return ret;
}
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index eda6e5d7..71ccaa5d 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -66,8 +66,7 @@ char *mm_create_device_identifier (guint vid,
const char *gsn,
const char *revision,
const char *model,
- const char *manf,
- gboolean debug);
+ const char *manf);
typedef struct CindResponse CindResponse;
GHashTable *mm_parse_cind_test_response (const char *reply, GError **error);
diff --git a/src/mm-modem.c b/src/mm-modem.c
index c65bee54..f8234723 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -18,7 +18,7 @@
#include <string.h>
#include <dbus/dbus-glib.h>
#include "mm-modem.h"
-#include "mm-options.h"
+#include "mm-log.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
#include "mm-marshal.h"
@@ -28,6 +28,7 @@ static void impl_modem_connect (MMModem *modem, const char *number, DBusGMethodI
static void impl_modem_disconnect (MMModem *modem, DBusGMethodInvocation *context);
static void impl_modem_get_ip4_config (MMModem *modem, DBusGMethodInvocation *context);
static void impl_modem_get_info (MMModem *modem, DBusGMethodInvocation *context);
+static void impl_modem_reset (MMModem *modem, DBusGMethodInvocation *context);
static void impl_modem_factory_reset (MMModem *modem, const char *code, DBusGMethodInvocation *context);
#include "mm-modem-glue.h"
@@ -478,6 +479,56 @@ impl_modem_get_info (MMModem *modem,
/*****************************************************************************/
static void
+reset_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModem *self = MM_MODEM (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise try to reset the modem */
+ if (!mm_modem_auth_finish (self, req, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ } else
+ mm_modem_reset (self, async_call_done, context);
+}
+
+static void
+impl_modem_reset (MMModem *modem, DBusGMethodInvocation *context)
+{
+ GError *error = NULL;
+
+ /* Make sure the caller is authorized to reset the device */
+ if (!mm_modem_auth_request (MM_MODEM (modem),
+ MM_AUTHORIZATION_DEVICE_CONTROL,
+ context,
+ reset_auth_cb,
+ NULL, NULL,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+void
+mm_modem_reset (MMModem *self,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM (self));
+ g_return_if_fail (callback != NULL);
+
+ if (MM_MODEM_GET_INTERFACE (self)->reset)
+ MM_MODEM_GET_INTERFACE (self)->reset (self, callback, user_data);
+ else
+ async_op_not_supported (self, callback, user_data);
+}
+
+/*****************************************************************************/
+
+static void
factory_reset_auth_cb (MMAuthRequest *req,
GObject *owner,
DBusGMethodInvocation *context,
@@ -704,22 +755,10 @@ mm_modem_set_state (MMModem *self,
dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
if (dbus_path) {
- if (mm_options_debug ()) {
- GTimeVal tv;
-
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> Modem %s: state changed (%s -> %s)",
- tv.tv_sec,
- tv.tv_usec,
- dbus_path,
- state_to_string (old_state),
- state_to_string (new_state));
- } else {
- g_message ("Modem %s: state changed (%s -> %s)",
- dbus_path,
- state_to_string (old_state),
- state_to_string (new_state));
- }
+ mm_info ("Modem %s: state changed (%s -> %s)",
+ dbus_path,
+ state_to_string (old_state),
+ state_to_string (new_state));
}
}
}
diff --git a/src/mm-modem.h b/src/mm-modem.h
index 1faf3838..8a755d88 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -194,6 +194,10 @@ struct _MMModem {
MMAuthRequest *req,
GError **error);
+ void (*reset) (MMModem *self,
+ MMModemFn callback,
+ gpointer user_data);
+
void (*factory_reset) (MMModem *self,
const char *code,
MMModemFn callback,
@@ -257,6 +261,10 @@ void mm_modem_set_charset (MMModem *self,
MMModemFn callback,
gpointer user_data);
+void mm_modem_reset (MMModem *self,
+ MMModemFn callback,
+ gpointer user_data);
+
void mm_modem_factory_reset (MMModem *self,
const char *code,
MMModemFn callback,
diff --git a/src/mm-options.c b/src/mm-options.c
deleted file mode 100644
index 7bbeefd6..00000000
--- a/src/mm-options.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details:
- *
- * Copyright (C) 2008 Novell, Inc.
- */
-
-#include <stdlib.h>
-#include <glib.h>
-#include "mm-options.h"
-
-static gboolean debug = FALSE;
-
-void
-mm_options_parse (int argc, char *argv[])
-{
- GOptionContext *opt_ctx;
- GError *error = NULL;
- GOptionEntry entries[] = {
- { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Output to console rather than syslog", NULL },
- { NULL }
- };
-
- opt_ctx = g_option_context_new (NULL);
- g_option_context_set_summary (opt_ctx, "DBus system service to communicate with modems.");
- g_option_context_add_main_entries (opt_ctx, entries, NULL);
-
- if (!g_option_context_parse (opt_ctx, &argc, &argv, &error)) {
- g_warning ("%s\n", error->message);
- g_error_free (error);
- exit (1);
- }
-
- g_option_context_free (opt_ctx);
-}
-
-void
-mm_options_set_debug (gboolean enabled)
-{
- debug = enabled;
-}
-
-gboolean
-mm_options_debug (void)
-{
- return debug;
-}
diff --git a/src/mm-options.h b/src/mm-options.h
deleted file mode 100644
index ce33e274..00000000
--- a/src/mm-options.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details:
- *
- * Copyright (C) 2008 Novell, Inc.
- */
-
-#ifndef MM_OPTIONS_H
-#define MM_OPTIONS_H
-
-void mm_options_parse (int argc, char *argv[]);
-void mm_options_set_debug (gboolean enabled);
-gboolean mm_options_debug (void);
-
-#endif /* MM_OPTIONS_H */
diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c
index 5a86b977..8d32e2a5 100644
--- a/src/mm-plugin-base.c
+++ b/src/mm-plugin-base.c
@@ -36,6 +36,7 @@
#include "mm-utils.h"
#include "libqcdm/src/commands.h"
#include "libqcdm/src/utils.h"
+#include "mm-log.h"
static void plugin_init (MMPlugin *plugin_class);
@@ -807,9 +808,9 @@ try_open (gpointer user_data)
task_priv->full_id = g_signal_connect (task_priv->probe_port, "buffer-full",
G_CALLBACK (port_buffer_full), task);
- g_debug ("(%s): probe requested by plugin '%s'",
- g_udev_device_get_name (port),
- mm_plugin_get_name (MM_PLUGIN (task_priv->plugin)));
+ mm_dbg ("(%s): probe requested by plugin '%s'",
+ g_udev_device_get_name (port),
+ mm_plugin_get_name (MM_PLUGIN (task_priv->plugin)));
mm_serial_port_flash (MM_SERIAL_PORT (task_priv->probe_port), 100, TRUE, flash_done, task);
}
diff --git a/src/mm-port.c b/src/mm-port.c
index b2018fe2..a1291d0b 100644
--- a/src/mm-port.c
+++ b/src/mm-port.c
@@ -19,7 +19,7 @@
#include <string.h>
#include "mm-port.h"
-#include "mm-options.h"
+#include "mm-log.h"
G_DEFINE_TYPE (MMPort, mm_port, G_TYPE_OBJECT)
@@ -47,6 +47,20 @@ typedef struct {
/*****************************************************************************/
const char *
+mm_port_subsys_to_name (MMPortSubsys psubsys)
+{
+ switch (psubsys) {
+ case MM_PORT_SUBSYS_TTY:
+ return "tty";
+ case MM_PORT_SUBSYS_NET:
+ return "net";
+ default:
+ break;
+ }
+ return "(unknown)";
+}
+
+const char *
mm_port_type_to_name (MMPortType ptype)
{
switch (ptype) {
@@ -161,16 +175,10 @@ mm_port_set_connected (MMPort *self, gboolean connected)
if (priv->connected != connected) {
priv->connected = connected;
g_object_notify (G_OBJECT (self), MM_PORT_CONNECTED);
- if (mm_options_debug()) {
- GTimeVal tv;
-
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s): port now %s",
- tv.tv_sec,
- tv.tv_usec,
- priv->device,
- connected ? "connected" : "disconnected");
- }
+
+ mm_dbg ("(%s): port now %s",
+ priv->device,
+ connected ? "connected" : "disconnected");
}
}
diff --git a/src/mm-port.h b/src/mm-port.h
index 43f78f46..4bcffd49 100644
--- a/src/mm-port.h
+++ b/src/mm-port.h
@@ -78,5 +78,7 @@ void mm_port_set_connected (MMPort *self, gboolean connected);
const char * mm_port_type_to_name (MMPortType ptype);
+const char * mm_port_subsys_to_name (MMPortSubsys psubsys);
+
#endif /* MM_PORT_H */
diff --git a/src/mm-properties-changed-signal.c b/src/mm-properties-changed-signal.c
index 633ff771..4408e80a 100644
--- a/src/mm-properties-changed-signal.c
+++ b/src/mm-properties-changed-signal.c
@@ -21,6 +21,7 @@
#include "mm-marshal.h"
#include "mm-properties-changed-signal.h"
#include "mm-properties-changed-glue.h"
+#include "mm-log.h"
#define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
#define DBUS_TYPE_G_ARRAY_OF_STRING (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING))
@@ -150,10 +151,10 @@ properties_changed (gpointer data)
{
char buf[2048] = { 0, };
g_hash_table_foreach (props, add_to_string, &buf);
- g_message ("%s: %s -> (%s) %s", __func__,
- G_OBJECT_TYPE_NAME (object),
- interface,
- buf);
+ mm_dbg ("%s: %s -> (%s) %s", __func__,
+ G_OBJECT_TYPE_NAME (object),
+ interface,
+ buf);
}
#endif
diff --git a/src/mm-qcdm-serial-port.c b/src/mm-qcdm-serial-port.c
index 7f4302c5..e467f2a2 100644
--- a/src/mm-qcdm-serial-port.c
+++ b/src/mm-qcdm-serial-port.c
@@ -21,9 +21,9 @@
#include "mm-qcdm-serial-port.h"
#include "mm-errors.h"
-#include "mm-options.h"
#include "libqcdm/src/com.h"
#include "libqcdm/src/utils.h"
+#include "mm-log.h"
G_DEFINE_TYPE (MMQcdmSerialPort, mm_qcdm_serial_port, MM_TYPE_SERIAL_PORT)
@@ -182,7 +182,6 @@ debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len)
{
static GString *debug = NULL;
const char *s = buf;
- GTimeVal tv;
if (!debug)
debug = g_string_sized_new (512);
@@ -192,12 +191,7 @@ debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len)
while (len--)
g_string_append_printf (debug, " %02x", (guint8) (*s++ & 0xFF));
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s): %s",
- tv.tv_sec,
- tv.tv_usec,
- mm_port_get_device (MM_PORT (port)),
- debug->str);
+ mm_dbg ("(%s): %s", mm_port_get_device (MM_PORT (port)), debug->str);
g_string_truncate (debug, 0);
}
diff --git a/src/mm-serial-parsers.c b/src/mm-serial-parsers.c
index 735ebd97..75bcce4d 100644
--- a/src/mm-serial-parsers.c
+++ b/src/mm-serial-parsers.c
@@ -19,6 +19,7 @@
#include "mm-serial-parsers.h"
#include "mm-errors.h"
+#include "mm-log.h"
/* Clean up the response by removing control characters like <CR><LF> etc */
static void
@@ -174,7 +175,7 @@ mm_serial_parser_v0_parse (gpointer data,
response_clean (response);
if (local_error) {
- g_debug ("Got failure code %d: %s", local_error->code, local_error->message);
+ mm_dbg ("Got failure code %d: %s", local_error->code, local_error->message);
g_propagate_error (error, local_error);
}
@@ -336,7 +337,7 @@ done:
response_clean (response);
if (local_error) {
- g_debug ("Got failure code %d: %s", local_error->code, local_error->message);
+ mm_dbg ("Got failure code %d: %s", local_error->code, local_error->message);
g_propagate_error (error, local_error);
}
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index 0f4d888e..bf2a98ab 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -30,7 +30,7 @@
#include "mm-serial-port.h"
#include "mm-errors.h"
-#include "mm-options.h"
+#include "mm-log.h"
static gboolean mm_serial_port_queue_process (gpointer data);
@@ -152,10 +152,10 @@ mm_serial_port_print_config (MMSerialPort *port, const char *detail)
return;
}
- g_message ("*** %s (%s): (%s) baud rate: %d (%s)",
- __func__, detail, mm_port_get_device (MM_PORT (port)),
- stbuf.c_cflag & CBAUD,
- baud_to_string (stbuf.c_cflag & CBAUD));
+ mm_info ("(%s): (%s) baud rate: %d (%s)",
+ detail, mm_port_get_device (MM_PORT (port)),
+ stbuf.c_cflag & CBAUD,
+ baud_to_string (stbuf.c_cflag & CBAUD));
}
#endif
@@ -350,7 +350,7 @@ serial_debug (MMSerialPort *self, const char *prefix, const char *buf, gsize len
{
g_return_if_fail (len > 0);
- if (mm_options_debug () && MM_SERIAL_PORT_GET_CLASS (self)->debug_log)
+ if (MM_SERIAL_PORT_GET_CLASS (self)->debug_log)
MM_SERIAL_PORT_GET_CLASS (self)->debug_log (self, prefix, buf, len);
}
@@ -686,7 +686,6 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
MMSerialPortPrivate *priv;
char *devfile;
const char *device;
- GTimeVal tv;
struct serial_struct sinfo;
g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
@@ -700,12 +699,7 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
goto success;
}
- if (mm_options_debug ()) {
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s) opening serial port...",
- tv.tv_sec, tv.tv_usec, device);
- } else
- g_message ("(%s) opening serial port...", device);
+ mm_info ("(%s) opening serial port...", device);
/* Only open a new file descriptor if we weren't given one already */
if (priv->fd < 0) {
@@ -767,11 +761,7 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
success:
priv->open_count++;
- if (mm_options_debug ()) {
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s) device open count is %d (open)",
- tv.tv_sec, tv.tv_usec, device, priv->open_count);
- }
+ mm_dbg ("(%s) device open count is %d (open)", device, priv->open_count);
return TRUE;
error:
@@ -794,7 +784,6 @@ mm_serial_port_close (MMSerialPort *self)
{
MMSerialPortPrivate *priv;
const char *device;
- GTimeVal tv;
int i;
g_return_if_fail (MM_IS_SERIAL_PORT (self));
@@ -806,11 +795,7 @@ mm_serial_port_close (MMSerialPort *self)
priv->open_count--;
- if (mm_options_debug ()) {
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s) device open count is %d (close)",
- tv.tv_sec, tv.tv_usec, device, priv->open_count);
- }
+ mm_dbg ("(%s) device open count is %d (close)", device, priv->open_count);
if (priv->open_count > 0)
return;
@@ -823,12 +808,7 @@ mm_serial_port_close (MMSerialPort *self)
if (priv->fd >= 0) {
GTimeVal tv_start, tv_end;
- g_get_current_time (&tv_start);
- if (mm_options_debug ()) {
- g_debug ("<%ld.%ld> (%s) closing serial port...",
- tv_start.tv_sec, tv_start.tv_usec, device);
- } else
- g_message ("(%s) closing serial port...", device);
+ mm_info ("(%s) closing serial port...", device);
mm_port_set_connected (MM_PORT (self), FALSE);
@@ -842,16 +822,16 @@ mm_serial_port_close (MMSerialPort *self)
mm_serial_port_flash_cancel (self);
+ g_get_current_time (&tv_start);
+
tcsetattr (priv->fd, TCSANOW, &priv->old_t);
tcflush (priv->fd, TCIOFLUSH);
close (priv->fd);
priv->fd = -1;
g_get_current_time (&tv_end);
- if (mm_options_debug ()) {
- g_debug ("<%ld.%ld> (%s) serial port closed",
- tv_end.tv_sec, tv_end.tv_usec, device);
- }
+
+ mm_info ("(%s) serial port closed", device);
/* Some ports don't respond to data and when close is called
* the serial layer waits up to 30 second (closing_wait) for
@@ -859,7 +839,7 @@ mm_serial_port_close (MMSerialPort *self)
* Log that. See GNOME bug #630670 for more details.
*/
if (tv_end.tv_sec - tv_start.tv_sec > 20)
- g_warning ("(%s): close blocked by driver for more than 20 seconds!", device);
+ mm_warn ("(%s): close blocked by driver for more than 20 seconds!", device);
}
/* Clear the command queue */
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index f0cbe61c..946916ff 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -17,6 +17,7 @@
#include <string.h>
#include "mm-modem-helpers.h"
+#include "mm-log.h"
typedef struct {
GPtrArray *solicited_creg;
@@ -722,6 +723,16 @@ test_cgreg2_x220_unsolicited (void *f, gpointer d)
}
static void
+test_creg2_s8500_wave_unsolicited (void *f, gpointer d)
+{
+ TestData *data = (TestData *) d;
+ const char *reply = "\r\n+CREG: 2,1,000B,2816, B, C2816\r\n";
+ const CregResult result = { 1, 0x000B, 0x2816, 0, 7, FALSE};
+
+ test_creg_match ("Samsung Wave S8500 CREG=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";
@@ -1069,8 +1080,7 @@ test_devid_item (void *f, gpointer d)
item->gsn,
item->revision,
item->model,
- item->manf,
- FALSE);
+ item->manf);
g_assert (devid);
if (strcmp (devid, item->devid))
g_message ("%s", devid);
@@ -1107,7 +1117,7 @@ test_cind_results (const char *desc,
compare = g_hash_table_lookup (results, expected->desc);
g_assert (compare);
- g_assert_cmpint (i, ==, cind_response_get_index (compare));
+ g_assert_cmpint (i + 1, ==, cind_response_get_index (compare));
g_assert_cmpint (expected->min, ==, cind_response_get_min (compare));
g_assert_cmpint (expected->max, ==, cind_response_get_max (compare));
}
@@ -1168,6 +1178,15 @@ test_data_free (TestData *data)
g_free (data);
}
+void
+_mm_log (const char *loc,
+ const char *func,
+ guint32 level,
+ const char *fmt,
+ ...)
+{
+ /* Dummy log function */
+}
#if GLIB_CHECK_VERSION(2,25,12)
typedef GTestFixtureFunc TCFunc;
@@ -1231,6 +1250,7 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_creg2_tm506_solicited, data));
g_test_suite_add (suite, TESTCASE (test_creg2_xu870_unsolicited_unregistered, data));
g_test_suite_add (suite, TESTCASE (test_creg2_md400_unsolicited, data));
+ g_test_suite_add (suite, TESTCASE (test_creg2_s8500_wave_unsolicited, data));
g_test_suite_add (suite, TESTCASE (test_cgreg1_solicited, data));
g_test_suite_add (suite, TESTCASE (test_cgreg1_unsolicited, data));
diff --git a/src/tests/test-qcdm-serial-port.c b/src/tests/test-qcdm-serial-port.c
index ab737c5e..3aeed6ab 100644
--- a/src/tests/test-qcdm-serial-port.c
+++ b/src/tests/test-qcdm-serial-port.c
@@ -31,6 +31,7 @@
#include "libqcdm/src/commands.h"
#include "libqcdm/src/utils.h"
#include "libqcdm/src/com.h"
+#include "mm-log.h"
typedef struct {
int master;
@@ -449,10 +450,14 @@ typedef void (*TCFunc)(void);
#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL)
#define TESTCASE_PTY(t, d) g_test_create_case (#t, sizeof (*d), d, (TCFunc) test_pty_create, (TCFunc) t, (TCFunc) test_pty_cleanup)
-gboolean mm_options_debug (void);
-gboolean mm_options_debug (void)
+void
+_mm_log (const char *loc,
+ const char *func,
+ guint32 level,
+ const char *fmt,
+ ...)
{
- return g_test_verbose ();
+ /* Dummy log function */
}
int main (int argc, char **argv)
diff --git a/test/ussd.py b/test/ussd.py
index 332cc172..2040f12e 100644..100755
--- a/test/ussd.py
+++ b/test/ussd.py
@@ -15,7 +15,7 @@
#
# Usage: ./test/ussd.py /org/freedesktop/ModemManager/Modems/0 '*130#'
-import sys, dbus
+import sys, dbus, re
MM_DBUS_SERVICE='org.freedesktop.ModemManager'
MM_DBUS_INTERFACE_USSD='org.freedesktop.ModemManager.Modem.Gsm.Ussd'
@@ -23,5 +23,22 @@ MM_DBUS_INTERFACE_USSD='org.freedesktop.ModemManager.Modem.Gsm.Ussd'
bus = dbus.SystemBus()
proxy = bus.get_object(MM_DBUS_SERVICE, sys.argv[1])
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_USSD)
-ret = modem.Initiate (sys.argv[2])
+
+if len(sys.argv) != 3:
+ print "Usage: %s dbus_object ussd"
+ sys.exit(1)
+else:
+ arg = sys.argv[2]
+
+# For testing purposes treat all "common" USSD sequences as initiate and the
+# rest (except for cancel) as response. See GSM 02.90.
+initiate_re = re.compile('[*#]{1,3}1[0-9][0-9].*#')
+
+if initiate_re.match(arg):
+ ret = modem.Initiate(arg)
+elif arg == "cancel":
+ ret = modem.Cancel()
+else:
+ ret = modem.Respond(arg)
print ret
+