Merge remote branch 'origin/master' into qcdm
This commit is contained in:
@@ -14,4 +14,5 @@ EXTRA_DIST = \
|
||||
mm-modem-gsm-sms.xml \
|
||||
mm-modem-simple.xml \
|
||||
mm-serial-error.xml \
|
||||
mm-modem-location.xml
|
||||
mm-modem-location.xml \
|
||||
mm-modem-gsm-ussd.xml
|
||||
|
@@ -33,6 +33,7 @@
|
||||
<xi:include href="mm-modem-gsm-network.xml"/>
|
||||
<xi:include href="mm-modem-gsm-sms.xml"/>
|
||||
<xi:include href="mm-modem-gsm-hso.xml"/>
|
||||
<xi:include href="mm-modem-gsm-ussd.xml"/>
|
||||
|
||||
<xi:include href="mm-serial-error.xml"/>
|
||||
<xi:include href="mm-modem-error.xml"/>
|
||||
|
78
introspection/mm-modem-gsm-ussd.xml
Normal file
78
introspection/mm-modem-gsm-ussd.xml
Normal file
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
|
||||
|
||||
<interface name="org.freedesktop.ModemManager.Modem.Gsm.Ussd">
|
||||
<method name="Initiate">
|
||||
<tp:docstring>
|
||||
Sends a USSD command string to the network initiating a USSD session.
|
||||
When the request is handled by the network, the method returns the
|
||||
response or an appropriate error. The network may be awaiting further
|
||||
response from the ME after returning from this method and no new command
|
||||
can be initiated until this one is cancelled or ended.
|
||||
</tp:docstring>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_gsm_ussd_initiate"/>
|
||||
<arg name="command" type="s" direction="in">
|
||||
<tp:docstring>
|
||||
The command to start the USSD session with.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg name="reply" type="s" direction="out">
|
||||
<tp:docstring>
|
||||
The network response to the command which started the USSD session.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="Respond">
|
||||
<tp:docstring>
|
||||
Respond to a USSD request that is either initiated by the mobile network,
|
||||
or that is awaiting further input after Initiate() was called.
|
||||
</tp:docstring>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_gsm_ussd_respond"/>
|
||||
<arg name="response" type="s" direction="in">
|
||||
<tp:docstring>
|
||||
The response to network-initiated USSD command, or a response to a
|
||||
request for further input.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="Cancel">
|
||||
<tp:docstring>
|
||||
Cancel an ongoing USSD session, either mobile or network initiated.
|
||||
</tp:docstring>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_gsm_ussd_cancel"/>
|
||||
</method>
|
||||
|
||||
<property name="State" type="s" access="read">
|
||||
<tp:docstring>
|
||||
Indicates the state of any ongoing USSD session. Values may be one of
|
||||
the following: "idle" (no active session), "active" (a session is active
|
||||
and the mobile is waiting for a response), "user-response" (the network
|
||||
is waiting for the client's response, which must be sent using Respond()).
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="NetworkNotification" type="s" access="read">
|
||||
<tp:docstring>
|
||||
Contains any network-initiated request to which no USSD response is
|
||||
required. When no USSD session is active, or when there is no network-
|
||||
initiated request, this property will be a zero-length string.
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="NetworkRequest" type="s" access="read">
|
||||
<tp:docstring>
|
||||
Contains any pending network-initiated request for a response. Client
|
||||
should call Respond() with the appropriate response to this request.
|
||||
When no USSD session is active, or when there is no pending
|
||||
network-initiated request, this property will be a zero-length string.
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
</interface>
|
||||
</node>
|
@@ -40,7 +40,6 @@ G_DEFINE_TYPE_EXTENDED (MMModemHuaweiGsm, mm_modem_huawei_gsm, MM_TYPE_GENERIC_G
|
||||
|
||||
typedef struct {
|
||||
/* Cached state */
|
||||
guint signal_quality;
|
||||
MMModemGsmBand band;
|
||||
} MMModemHuaweiGsmPrivate;
|
||||
|
||||
@@ -369,29 +368,6 @@ get_band (MMModemGsmNetwork *modem,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_signal_quality (MMModemGsmNetwork *modem,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (modem);
|
||||
|
||||
if (priv->signal_quality) {
|
||||
/* have cached signal quality (from an unsolicited message). Use that */
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
|
||||
mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->signal_quality), NULL);
|
||||
mm_callback_info_schedule (info);
|
||||
} else {
|
||||
/* Use the generic implementation */
|
||||
MMModemGsmNetwork *parent_gsm_network_iface;
|
||||
|
||||
parent_gsm_network_iface = g_type_interface_peek_parent (MM_MODEM_GSM_NETWORK_GET_INTERFACE (modem));
|
||||
parent_gsm_network_iface->get_signal_quality (modem, callback, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unsolicited message handlers */
|
||||
|
||||
static void
|
||||
@@ -400,24 +376,22 @@ handle_signal_quality_change (MMAtSerialPort *port,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (user_data);
|
||||
MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self);
|
||||
char *str;
|
||||
int quality;
|
||||
int quality = 0;
|
||||
|
||||
str = g_match_info_fetch (match_info, 1);
|
||||
quality = atoi (str);
|
||||
g_free (str);
|
||||
|
||||
if (quality == 99)
|
||||
if (quality == 99) {
|
||||
/* 99 means unknown */
|
||||
quality = 0;
|
||||
else
|
||||
} else {
|
||||
/* Normalize the quality */
|
||||
quality = quality * 100 / 31;
|
||||
quality = CLAMP (quality, 0, 31) * 100 / 31;
|
||||
}
|
||||
|
||||
g_debug ("Signal quality: %d", quality);
|
||||
priv->signal_quality = (guint32) quality;
|
||||
mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (self), (guint32) quality);
|
||||
mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (self), (guint32) quality);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -568,7 +542,6 @@ modem_gsm_network_init (MMModemGsmNetwork *class)
|
||||
{
|
||||
class->set_band = set_band;
|
||||
class->get_band = get_band;
|
||||
class->get_signal_quality = get_signal_quality;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -52,11 +52,6 @@ G_DEFINE_TYPE_EXTENDED (MMModemMbm, mm_modem_mbm, MM_TYPE_GENERIC_GSM, 0,
|
||||
#define MBM_NETWORK_MODE_2G 5
|
||||
#define MBM_NETWORK_MODE_3G 6
|
||||
|
||||
#define MBM_ERINFO_2G_GPRS 1
|
||||
#define MBM_ERINFO_2G_EGPRS 2
|
||||
#define MBM_ERINFO_3G_UMTS 1
|
||||
#define MBM_ERINFO_3G_HSDPA 2
|
||||
|
||||
typedef struct {
|
||||
guint reg_id;
|
||||
gboolean have_emrdy;
|
||||
@@ -129,9 +124,6 @@ register_done (gpointer user_data)
|
||||
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, "+CREG=1", 3, NULL, NULL);
|
||||
mm_at_serial_port_queue_command (primary, "+CMER=3,0,0,1", 3, NULL, NULL);
|
||||
|
||||
parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GSM_NETWORK_GET_INTERFACE (self));
|
||||
parent_modem_iface->do_register (MM_MODEM_GSM_NETWORK (self),
|
||||
reg_data->network_id,
|
||||
@@ -214,57 +206,47 @@ set_allowed_mode (MMGenericGsm *gsm,
|
||||
g_free (command);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
get_network_mode_done (MMAtSerialPort *port,
|
||||
GString *response,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
mbm_erinfo_received (MMAtSerialPort *port,
|
||||
GMatchInfo *info,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
char *erinfo;
|
||||
int mode = 0, gsm = 0, umts = 0;
|
||||
gboolean parsed = FALSE;
|
||||
MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
|
||||
char *str;
|
||||
|
||||
if (error) {
|
||||
info->error = g_error_copy (error);
|
||||
goto done;
|
||||
str = g_match_info_fetch (info, 2);
|
||||
if (str) {
|
||||
switch (atoi (str)) {
|
||||
case 1:
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_GPRS;
|
||||
break;
|
||||
case 2:
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_EDGE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free (str);
|
||||
|
||||
erinfo = strstr (response->str, "*ERINFO:");
|
||||
if (!erinfo)
|
||||
goto done;
|
||||
|
||||
if (sscanf (erinfo + 8, "%d,%d,%d", &mode, &gsm, &umts) != 3)
|
||||
goto done;
|
||||
|
||||
if (gsm || umts) {
|
||||
MMModemGsmMode mm_mode = MM_MODEM_GSM_MODE_ANY;
|
||||
|
||||
if (gsm == MBM_ERINFO_2G_GPRS)
|
||||
mm_mode = MM_MODEM_GSM_MODE_GPRS;
|
||||
else if (gsm == MBM_ERINFO_2G_EGPRS)
|
||||
mm_mode = MM_MODEM_GSM_MODE_EDGE;
|
||||
else if (umts == MBM_ERINFO_3G_UMTS)
|
||||
mm_mode = MM_MODEM_GSM_MODE_UMTS;
|
||||
else if (umts == MBM_ERINFO_3G_HSDPA)
|
||||
mm_mode = MM_MODEM_GSM_MODE_HSDPA;
|
||||
else
|
||||
g_debug ("%s unknown network mode %d,%d", __FUNCTION__, gsm, umts);
|
||||
|
||||
mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_mode), NULL);
|
||||
parsed = TRUE;
|
||||
/* 3G modes take precedence */
|
||||
str = g_match_info_fetch (info, 3);
|
||||
if (str) {
|
||||
switch (atoi (str)) {
|
||||
case 1:
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_UMTS;
|
||||
break;
|
||||
case 2:
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_HSDPA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free (str);
|
||||
|
||||
done:
|
||||
if (!error && !parsed) {
|
||||
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"Could not parse network mode results");
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (user_data), act);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
get_allowed_mode_done (MMAtSerialPort *port,
|
||||
@@ -364,6 +346,10 @@ mbm_enable_done (MMAtSerialPort *port,
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
/* Start unsolicited signal strength and access technology responses */
|
||||
mm_at_serial_port_queue_command (port, "+CMER=3,0,0,1", 3, NULL, NULL);
|
||||
mm_at_serial_port_queue_command (port, "*ERINFO=1", 3, NULL, NULL);
|
||||
|
||||
mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info);
|
||||
}
|
||||
|
||||
@@ -456,10 +442,10 @@ typedef struct {
|
||||
} DisableInfo;
|
||||
|
||||
static void
|
||||
disable_creg_cmer_done (MMAtSerialPort *port,
|
||||
GString *response,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
disable_unsolicited_done (MMAtSerialPort *port,
|
||||
GString *response,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
|
||||
{
|
||||
MMModem *parent_modem_iface;
|
||||
@@ -486,8 +472,8 @@ disable (MMModem *modem,
|
||||
primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
|
||||
g_assert (primary);
|
||||
|
||||
/* Turn off unsolicited +CIEV signal strength indicator */
|
||||
mm_at_serial_port_queue_command (primary, "+CREG=0;+CMER=0", 5, disable_creg_cmer_done, info);
|
||||
/* Turn off unsolicited responses */
|
||||
mm_at_serial_port_queue_command (primary, "+CMER=0;*ERINFO=0", 5, disable_unsolicited_done, info);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -551,18 +537,20 @@ mbm_ciev_received (MMAtSerialPort *port,
|
||||
gpointer user_data)
|
||||
{
|
||||
int quality = 0, ind = 0;
|
||||
const char *str;
|
||||
char *str;
|
||||
|
||||
str = g_match_info_fetch (info, 1);
|
||||
if (str)
|
||||
ind = atoi (str);
|
||||
g_free (str);
|
||||
|
||||
if (ind == MBM_SIGNAL_INDICATOR) {
|
||||
str = g_match_info_fetch (info, 2);
|
||||
if (str) {
|
||||
quality = atoi (str);
|
||||
mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (user_data), quality * 20);
|
||||
mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (user_data), quality * 20);
|
||||
}
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,11 +580,12 @@ mbm_e2nap_received (MMAtSerialPort *port,
|
||||
gpointer user_data)
|
||||
{
|
||||
int state = 0;
|
||||
const char *str;
|
||||
char *str;
|
||||
|
||||
str = g_match_info_fetch (info, 1);
|
||||
if (str)
|
||||
state = atoi (str);
|
||||
g_free (str);
|
||||
|
||||
if (MBM_E2NAP_DISCONNECTED == state) {
|
||||
g_debug ("%s: disconnected", __func__);
|
||||
@@ -791,17 +780,19 @@ grab_port (MMModem *modem,
|
||||
}
|
||||
|
||||
port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
|
||||
if (port && MM_IS_AT_SERIAL_PORT (port) && (ptype == MM_PORT_TYPE_PRIMARY)) {
|
||||
if (port && MM_IS_AT_SERIAL_PORT (port)) {
|
||||
GRegex *regex;
|
||||
|
||||
if (ptype == MM_PORT_TYPE_PRIMARY) {
|
||||
regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_e2nap_received, modem, NULL);
|
||||
g_regex_unref (regex);
|
||||
}
|
||||
|
||||
regex = g_regex_new ("\\r\\n\\*EMRDY: \\d\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_emrdy_received, modem, NULL);
|
||||
g_regex_unref (regex);
|
||||
|
||||
regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_e2nap_received, modem, 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 (MM_AT_SERIAL_PORT (port), regex, mbm_pacsp_received, modem, NULL);
|
||||
g_regex_unref (regex);
|
||||
@@ -812,12 +803,16 @@ grab_port (MMModem *modem,
|
||||
|
||||
/* also consume unsolicited mbm messages we are not interested in them - see LP: #416418 */
|
||||
regex = g_regex_new ("\\R\\*ESTKSMENU:.*\\R", G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_MULTILINE | G_REGEX_NEWLINE_CRLF, G_REGEX_MATCH_NEWLINE_CRLF, NULL);
|
||||
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, modem, NULL);
|
||||
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL);
|
||||
g_regex_unref (regex);
|
||||
|
||||
regex = g_regex_new ("\\r\\n\\*EMWI: (\\d),(\\d).*\\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);
|
||||
|
||||
regex = g_regex_new ("\\r\\n\\*ERINFO:\\s*(\\d),(\\d),(\\d).*\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_erinfo_received, modem, NULL);
|
||||
g_regex_unref (regex);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@@ -48,13 +48,27 @@ mm_modem_novatel_gsm_new (const char *device,
|
||||
/* Modem class override functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
dmat_callback2 (MMAtSerialPort *port,
|
||||
GString *response,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
mm_serial_port_close (MM_SERIAL_PORT (port));
|
||||
}
|
||||
|
||||
static void
|
||||
dmat_callback (MMAtSerialPort *port,
|
||||
GString *response,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
mm_serial_port_close (MM_SERIAL_PORT (port));
|
||||
if (error) {
|
||||
/* Try it again */
|
||||
if (mm_serial_port_open (MM_SERIAL_PORT (port), NULL))
|
||||
mm_at_serial_port_queue_command (port, "$NWDMAT=1", 2, dmat_callback2, NULL);
|
||||
} else
|
||||
mm_serial_port_close (MM_SERIAL_PORT (port));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@@ -52,6 +52,39 @@ mm_modem_zte_new (const char *device,
|
||||
NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
zte_access_tech_changed (MMAtSerialPort *port,
|
||||
GMatchInfo *info,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
|
||||
char *str;
|
||||
|
||||
str = g_match_info_fetch (info, 1);
|
||||
if (str) {
|
||||
/* Better technologies are listed first since modem sometimes says
|
||||
* stuff like "GPRS/EDGE" and that should be handled as EDGE.
|
||||
*/
|
||||
if (strstr (str, "HSPA"))
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_HSPA;
|
||||
else if (strstr (str, "HSUPA"))
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_HSUPA;
|
||||
else if (strstr (str, "HSDPA"))
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_HSDPA;
|
||||
else if (strstr (str, "UMTS"))
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_UMTS;
|
||||
else if (strstr (str, "EDGE"))
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_EDGE;
|
||||
else if (strstr (str, "GPRS"))
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_GPRS;
|
||||
else if (strstr (str, "GSM"))
|
||||
act = MM_MODEM_GSM_ACCESS_TECH_GSM;
|
||||
}
|
||||
g_free (str);
|
||||
|
||||
mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (user_data), act);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Modem class override functions */
|
||||
/*****************************************************************************/
|
||||
@@ -223,8 +256,8 @@ grab_port (MMModem *modem,
|
||||
g_regex_unref (regex);
|
||||
|
||||
/* Current network and service domain */
|
||||
regex = g_regex_new ("\\r\\n\\+ZPASR: (.*)\\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);
|
||||
regex = g_regex_new ("\\r\\n\\+ZPASR:\\s*(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, zte_access_tech_changed, modem, NULL);
|
||||
g_regex_unref (regex);
|
||||
|
||||
/* SIM request to Build Main Menu */
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include "mm-manager.h"
|
||||
@@ -33,8 +34,11 @@ mm_signal_handler (int signo)
|
||||
mm_options_set_debug (!mm_options_debug ());
|
||||
else if (signo == SIGINT || signo == SIGTERM) {
|
||||
g_message ("Caught signal %d, shutting down...", signo);
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
if (loop)
|
||||
g_main_loop_quit (loop);
|
||||
else
|
||||
_exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -358,6 +358,9 @@ enable_all_done (MMModem *modem, GError *error, gpointer user_data)
|
||||
if (error)
|
||||
info->error = g_error_copy (error);
|
||||
else {
|
||||
/* Try to enable XON/XOFF flow control */
|
||||
mm_at_serial_port_queue_command (priv->primary, "+IFC=1,1", 3, NULL, NULL);
|
||||
|
||||
/* Open up the second port, if one exists */
|
||||
if (priv->secondary) {
|
||||
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &info->error)) {
|
||||
|
@@ -79,6 +79,8 @@ typedef struct {
|
||||
guint pending_reg_id;
|
||||
MMCallbackInfo *pending_reg_info;
|
||||
|
||||
guint signal_quality_id;
|
||||
time_t signal_quality_timestamp;
|
||||
guint32 signal_quality;
|
||||
guint32 cid;
|
||||
|
||||
@@ -113,6 +115,17 @@ static gboolean handle_reg_status_response (MMGenericGsm *self,
|
||||
|
||||
static MMModemGsmAccessTech etsi_act_to_mm_act (gint act);
|
||||
|
||||
static void _internal_update_access_technology (MMGenericGsm *modem,
|
||||
MMModemGsmAccessTech act);
|
||||
|
||||
static void reg_info_updated (MMGenericGsm *self,
|
||||
gboolean update_rs,
|
||||
MMModemGsmNetworkRegStatus status,
|
||||
gboolean update_code,
|
||||
const char *oper_code,
|
||||
gboolean update_name,
|
||||
const char *oper_name);
|
||||
|
||||
MMModem *
|
||||
mm_generic_gsm_new (const char *device,
|
||||
const char *driver,
|
||||
@@ -145,14 +158,6 @@ mm_generic_gsm_get_cid (MMGenericGsm *modem)
|
||||
return MM_GENERIC_GSM_GET_PRIVATE (modem)->cid;
|
||||
}
|
||||
|
||||
static void
|
||||
got_signal_quality (MMModem *modem,
|
||||
guint32 result,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *result;
|
||||
const char *normalized;
|
||||
@@ -699,6 +704,9 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self,
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to enable XON/XOFF flow control */
|
||||
mm_at_serial_port_queue_command (priv->primary, "+IFC=1,1", 3, NULL, NULL);
|
||||
|
||||
/* Get allowed mode */
|
||||
if (MM_GENERIC_GSM_GET_CLASS (self)->get_allowed_mode)
|
||||
MM_GENERIC_GSM_GET_CLASS (self)->get_allowed_mode (self, get_allowed_mode_done, NULL);
|
||||
@@ -842,13 +850,18 @@ disable_done (MMAtSerialPort *port,
|
||||
|
||||
info->error = mm_modem_check_removed (info->modem, error);
|
||||
if (!info->error) {
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
|
||||
MMGenericGsm *self = MM_GENERIC_GSM (info->modem);
|
||||
|
||||
mm_serial_port_close (MM_SERIAL_PORT (port));
|
||||
mm_modem_set_state (MM_MODEM (info->modem),
|
||||
MM_MODEM_STATE_DISABLED,
|
||||
MM_MODEM_STATE_REASON_NONE);
|
||||
priv->reg_status = MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN;
|
||||
|
||||
/* Clear out registration info */
|
||||
reg_info_updated (self,
|
||||
TRUE, MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN,
|
||||
TRUE, NULL,
|
||||
TRUE, NULL);
|
||||
}
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
@@ -903,11 +916,16 @@ disable (MMModem *modem,
|
||||
priv->poll_id = 0;
|
||||
}
|
||||
|
||||
if (priv->signal_quality_id) {
|
||||
g_source_remove (priv->signal_quality_id);
|
||||
priv->signal_quality_id = 0;
|
||||
}
|
||||
|
||||
priv->lac[0] = 0;
|
||||
priv->lac[1] = 0;
|
||||
priv->cell_id[0] = 0;
|
||||
priv->cell_id[1] = 0;
|
||||
mm_generic_gsm_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
|
||||
_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)))
|
||||
@@ -1268,6 +1286,49 @@ change_pin (MMModemGsmCard *modem,
|
||||
g_free (command);
|
||||
}
|
||||
|
||||
static void
|
||||
reg_info_updated (MMGenericGsm *self,
|
||||
gboolean update_rs,
|
||||
MMModemGsmNetworkRegStatus status,
|
||||
gboolean update_code,
|
||||
const char *oper_code,
|
||||
gboolean update_name,
|
||||
const char *oper_name)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
gboolean changed = FALSE;
|
||||
|
||||
if (update_rs) {
|
||||
if (status != priv->reg_status) {
|
||||
priv->reg_status = status;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_code) {
|
||||
if (g_strcmp0 (oper_code, priv->oper_code) != 0) {
|
||||
g_free (priv->oper_code);
|
||||
priv->oper_code = g_strdup (oper_code);
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_name) {
|
||||
if (g_strcmp0 (oper_name, priv->oper_name) != 0) {
|
||||
g_free (priv->oper_name);
|
||||
priv->oper_name = g_strdup (oper_name);
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (self),
|
||||
priv->reg_status,
|
||||
priv->oper_code,
|
||||
priv->oper_name);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
parse_operator (const char *reply)
|
||||
{
|
||||
@@ -1300,18 +1361,14 @@ read_operator_code_done (MMAtSerialPort *port,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
|
||||
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
||||
char *oper;
|
||||
|
||||
if (error)
|
||||
return;
|
||||
|
||||
oper = parse_operator (response->str);
|
||||
if (!oper)
|
||||
return;
|
||||
|
||||
g_free (priv->oper_code);
|
||||
priv->oper_code = oper;
|
||||
if (!error) {
|
||||
oper = parse_operator (response->str);
|
||||
if (oper)
|
||||
reg_info_updated (self, FALSE, 0, TRUE, oper, FALSE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1320,23 +1377,14 @@ read_operator_name_done (MMAtSerialPort *port,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
|
||||
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
||||
char *oper;
|
||||
|
||||
if (error)
|
||||
return;
|
||||
|
||||
oper = parse_operator (response->str);
|
||||
if (!oper)
|
||||
return;
|
||||
|
||||
g_free (priv->oper_name);
|
||||
priv->oper_name = oper;
|
||||
|
||||
mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (user_data),
|
||||
priv->reg_status,
|
||||
priv->oper_code,
|
||||
priv->oper_name);
|
||||
if (!error) {
|
||||
oper = parse_operator (response->str);
|
||||
if (oper)
|
||||
reg_info_updated (self, FALSE, 0, FALSE, NULL, TRUE, oper);
|
||||
}
|
||||
}
|
||||
|
||||
/* Registration */
|
||||
@@ -1363,6 +1411,15 @@ mm_generic_gsm_pending_registration_stop (MMGenericGsm *modem)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
got_signal_quality (MMModem *modem,
|
||||
guint32 quality,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (modem), quality);
|
||||
}
|
||||
|
||||
void
|
||||
mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
|
||||
MMModemGsmNetworkRegStatus status)
|
||||
@@ -1383,14 +1440,8 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
|
||||
mm_at_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem);
|
||||
mm_at_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem);
|
||||
mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL);
|
||||
} else {
|
||||
g_free (priv->oper_code);
|
||||
g_free (priv->oper_name);
|
||||
priv->oper_code = priv->oper_name = NULL;
|
||||
|
||||
mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (modem), priv->reg_status,
|
||||
priv->oper_code, priv->oper_name);
|
||||
}
|
||||
} else
|
||||
reg_info_updated (MM_GENERIC_GSM (modem), FALSE, 0, TRUE, NULL, TRUE, NULL);
|
||||
|
||||
mm_generic_gsm_update_enabled_state (modem, TRUE, MM_MODEM_STATE_REASON_NONE);
|
||||
}
|
||||
@@ -1480,14 +1531,21 @@ reg_state_changed (MMAtSerialPort *port,
|
||||
return;
|
||||
}
|
||||
|
||||
if (reg_status_updated (self, state, NULL)) {
|
||||
/* If registration is finished (either registered or failed) but the
|
||||
* registration query hasn't completed yet, just remove the timeout and
|
||||
* let the registration query complete.
|
||||
*/
|
||||
if (priv->pending_reg_id) {
|
||||
g_source_remove (priv->pending_reg_id);
|
||||
priv->pending_reg_id = 0;
|
||||
/* Don't update reg state on CGREG responses since for many devices it's
|
||||
* unclear what that registration state that actually reflects. We'll
|
||||
* take CGREG registration state into account later when we have a more
|
||||
* consistent way of handling it.
|
||||
*/
|
||||
if (cgreg == FALSE) {
|
||||
if (reg_status_updated (self, state, NULL)) {
|
||||
/* If registration is finished (either registered or failed) but the
|
||||
* registration query hasn't completed yet, just remove the timeout and
|
||||
* let the registration query complete.
|
||||
*/
|
||||
if (priv->pending_reg_id) {
|
||||
g_source_remove (priv->pending_reg_id);
|
||||
priv->pending_reg_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1668,7 +1726,11 @@ registration_timed_out (gpointer data)
|
||||
|
||||
g_warn_if_fail (info == priv->pending_reg_info);
|
||||
|
||||
priv->reg_status = MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE;
|
||||
/* Clear out registration info */
|
||||
reg_info_updated (MM_GENERIC_GSM (info->modem),
|
||||
TRUE, MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE,
|
||||
TRUE, NULL,
|
||||
TRUE, NULL);
|
||||
|
||||
info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NETWORK_TIMEOUT);
|
||||
mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (info->modem));
|
||||
@@ -2133,26 +2195,91 @@ set_apn (MMModemGsmNetwork *modem,
|
||||
|
||||
/* GetSignalQuality */
|
||||
|
||||
static gboolean
|
||||
emit_signal_quality_change (gpointer user_data)
|
||||
{
|
||||
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
|
||||
priv->signal_quality_id = 0;
|
||||
priv->signal_quality_timestamp = time (NULL);
|
||||
mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (self), priv->signal_quality);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
mm_generic_gsm_update_signal_quality (MMGenericGsm *self, guint32 quality)
|
||||
{
|
||||
MMGenericGsmPrivate *priv;
|
||||
guint delay = 0;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (MM_IS_GENERIC_GSM (self));
|
||||
g_return_if_fail (quality <= 100);
|
||||
|
||||
priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
|
||||
if (priv->signal_quality == quality)
|
||||
return;
|
||||
|
||||
priv->signal_quality = quality;
|
||||
|
||||
/* Some modems will send unsolcited signal quality changes quite often,
|
||||
* so rate-limit them to every few seconds. Track the last time we
|
||||
* emitted signal quality so that we send the signal immediately if there
|
||||
* haven't been any updates in a while.
|
||||
*/
|
||||
if (!priv->signal_quality_id) {
|
||||
if (priv->signal_quality_timestamp > 0) {
|
||||
time_t curtime;
|
||||
long int diff;
|
||||
|
||||
curtime = time (NULL);
|
||||
diff = curtime - priv->signal_quality_timestamp;
|
||||
if (diff == 0) {
|
||||
/* If the device is sending more than one update per second,
|
||||
* make sure we don't spam clients with signals.
|
||||
*/
|
||||
delay = 3;
|
||||
} else if ((diff > 0) && (diff <= 3)) {
|
||||
/* Emitted an update less than 3 seconds ago; schedule an update
|
||||
* 3 seconds after the previous one.
|
||||
*/
|
||||
delay = (guint) diff;
|
||||
} else {
|
||||
/* Otherwise, we haven't emitted an update in the last 3 seconds,
|
||||
* or the user turned their clock back, or something like that.
|
||||
*/
|
||||
delay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
priv->signal_quality_id = g_timeout_add_seconds (delay,
|
||||
emit_signal_quality_change,
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_signal_quality_done (MMAtSerialPort *port,
|
||||
GString *response,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMGenericGsmPrivate *priv;
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
char *reply = response->str;
|
||||
gboolean parsed = FALSE;
|
||||
|
||||
if (error)
|
||||
info->error = g_error_copy (error);
|
||||
else if (!strncmp (reply, "+CSQ: ", 6)) {
|
||||
info->error = mm_modem_check_removed (info->modem, error);
|
||||
if (info->error)
|
||||
goto done;
|
||||
|
||||
if (!strncmp (reply, "+CSQ: ", 6)) {
|
||||
/* Got valid reply */
|
||||
int quality;
|
||||
int ber;
|
||||
|
||||
reply += 6;
|
||||
|
||||
if (sscanf (reply, "%d, %d", &quality, &ber)) {
|
||||
if (sscanf (reply + 6, "%d, %d", &quality, &ber)) {
|
||||
/* 99 means unknown */
|
||||
if (quality == 99) {
|
||||
info->error = g_error_new_literal (MM_MOBILE_ERROR,
|
||||
@@ -2162,15 +2289,19 @@ get_signal_quality_done (MMAtSerialPort *port,
|
||||
/* Normalize the quality */
|
||||
quality = CLAMP (quality, 0, 31) * 100 / 31;
|
||||
|
||||
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
|
||||
priv->signal_quality = quality;
|
||||
mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (info->modem), quality);
|
||||
mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
|
||||
}
|
||||
} else
|
||||
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"Could not parse signal quality results");
|
||||
parsed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parsed && !info->error) {
|
||||
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"Could not parse signal quality results");
|
||||
}
|
||||
|
||||
done:
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
@@ -2185,7 +2316,6 @@ get_signal_quality (MMModemGsmNetwork *modem,
|
||||
|
||||
connected = mm_port_get_connected (MM_PORT (priv->primary));
|
||||
if (connected && !priv->secondary) {
|
||||
g_message ("Returning saved signal quality %d", priv->signal_quality);
|
||||
callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data);
|
||||
return;
|
||||
}
|
||||
@@ -2221,19 +2351,19 @@ etsi_act_to_mm_act (gint act)
|
||||
while (iter->mm_act != MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) {
|
||||
if (iter->etsi_act == act)
|
||||
return iter->mm_act;
|
||||
iter++;
|
||||
}
|
||||
return MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
|
||||
}
|
||||
|
||||
void
|
||||
mm_generic_gsm_update_access_technology (MMGenericGsm *modem,
|
||||
MMModemGsmAccessTech act)
|
||||
static void
|
||||
_internal_update_access_technology (MMGenericGsm *modem,
|
||||
MMModemGsmAccessTech act)
|
||||
{
|
||||
MMGenericGsmPrivate *priv;
|
||||
|
||||
g_return_if_fail (modem != NULL);
|
||||
g_return_if_fail (MM_IS_GENERIC_GSM (modem));
|
||||
|
||||
g_return_if_fail (act >= MM_MODEM_GSM_ACCESS_TECH_UNKNOWN && act <= MM_MODEM_GSM_ACCESS_TECH_LAST);
|
||||
|
||||
priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
|
||||
@@ -2250,6 +2380,18 @@ mm_generic_gsm_update_access_technology (MMGenericGsm *modem,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mm_generic_gsm_update_access_technology (MMGenericGsm *self,
|
||||
MMModemGsmAccessTech act)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (MM_IS_GENERIC_GSM (self));
|
||||
|
||||
/* For plugins, don't update the access tech when the modem isn't enabled */
|
||||
if (mm_modem_get_state (MM_MODEM (self)) >= MM_MODEM_STATE_ENABLED)
|
||||
_internal_update_access_technology (self, act);
|
||||
}
|
||||
|
||||
void
|
||||
mm_generic_gsm_update_allowed_mode (MMGenericGsm *self,
|
||||
MMModemGsmAllowedMode mode)
|
||||
@@ -2509,8 +2651,6 @@ simple_connect (MMModemSimple *simple,
|
||||
simple_state_machine (MM_MODEM (simple), NULL, info);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
simple_free_gvalue (gpointer data)
|
||||
{
|
||||
@@ -2542,16 +2682,39 @@ simple_string_value (const char *str)
|
||||
return val;
|
||||
}
|
||||
|
||||
#define NOTDONE_TAG "not-done"
|
||||
#define SS_HASH_TAG "simple-get-status"
|
||||
|
||||
static void
|
||||
simple_status_complete_item (MMCallbackInfo *info)
|
||||
{
|
||||
guint32 completed = GPOINTER_TO_UINT (mm_callback_info_get_data (info, NOTDONE_TAG));
|
||||
|
||||
g_warn_if_fail (completed > 0);
|
||||
|
||||
/* Decrement the number of outstanding calls and if there aren't any left,
|
||||
* schedule the callback info completion.
|
||||
*/
|
||||
completed--;
|
||||
mm_callback_info_set_data (info, NOTDONE_TAG, GUINT_TO_POINTER (completed), NULL);
|
||||
if (completed == 0)
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_status_got_signal_quality (MMModem *modem,
|
||||
guint32 result,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (error)
|
||||
g_warning ("Error getting signal quality: %s", error->message);
|
||||
else
|
||||
g_hash_table_insert ((GHashTable *) user_data, "signal_quality", simple_uint_value (result));
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
GHashTable *properties;
|
||||
|
||||
if (!error) {
|
||||
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
|
||||
g_hash_table_insert (properties, "signal_quality", simple_uint_value (result));
|
||||
}
|
||||
simple_status_complete_item (info);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2560,9 +2723,14 @@ simple_status_got_band (MMModem *modem,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* Ignore band errors since there's no generic implementation for it */
|
||||
if (!error)
|
||||
g_hash_table_insert ((GHashTable *) user_data, "band", simple_uint_value (result));
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
GHashTable *properties;
|
||||
|
||||
if (!error) {
|
||||
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
|
||||
g_hash_table_insert (properties, "band", simple_uint_value (result));
|
||||
}
|
||||
simple_status_complete_item (info);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2576,17 +2744,15 @@ simple_status_got_reg_info (MMModemGsmNetwork *modem,
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
GHashTable *properties;
|
||||
|
||||
if (error)
|
||||
info->error = g_error_copy (error);
|
||||
else {
|
||||
properties = (GHashTable *) mm_callback_info_get_data (info, "simple-get-status");
|
||||
|
||||
info->error = mm_modem_check_removed ((MMModem *) modem, error);
|
||||
if (!info->error) {
|
||||
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
|
||||
|
||||
g_hash_table_insert (properties, "registration_status", simple_uint_value (status));
|
||||
g_hash_table_insert (properties, "operator_code", simple_string_value (oper_code));
|
||||
g_hash_table_insert (properties, "operator_name", simple_string_value (oper_name));
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
simple_status_complete_item (info);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2595,7 +2761,7 @@ simple_get_status_invoke (MMCallbackInfo *info)
|
||||
MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback;
|
||||
|
||||
callback (MM_MODEM_SIMPLE (info->modem),
|
||||
(GHashTable *) mm_callback_info_get_data (info, "simple-get-status"),
|
||||
(GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG),
|
||||
info->error, info->user_data);
|
||||
}
|
||||
|
||||
@@ -2615,12 +2781,15 @@ simple_get_status (MMModemSimple *simple,
|
||||
G_CALLBACK (callback),
|
||||
user_data);
|
||||
|
||||
properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, simple_free_gvalue);
|
||||
mm_callback_info_set_data (info, "simple-get-status", properties, (GDestroyNotify) g_hash_table_unref);
|
||||
properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, simple_free_gvalue);
|
||||
mm_callback_info_set_data (info, SS_HASH_TAG, properties, (GDestroyNotify) g_hash_table_unref);
|
||||
|
||||
mm_modem_gsm_network_get_signal_quality (gsm, simple_status_got_signal_quality, properties);
|
||||
mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties);
|
||||
mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, properties);
|
||||
mm_modem_gsm_network_get_signal_quality (gsm, simple_status_got_signal_quality, info);
|
||||
mm_modem_gsm_network_get_band (gsm, simple_status_got_band, info);
|
||||
mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, info);
|
||||
|
||||
/* 3 calls to complete before scheduling the callback: (signal, band, reginfo) */
|
||||
mm_callback_info_set_data (info, NOTDONE_TAG, GUINT_TO_POINTER (3), NULL);
|
||||
|
||||
if (priv->act > -1) {
|
||||
/* Deprecated key */
|
||||
@@ -2791,6 +2960,11 @@ finalize (GObject *object)
|
||||
priv->poll_id = 0;
|
||||
}
|
||||
|
||||
if (priv->signal_quality_id) {
|
||||
g_source_remove (priv->signal_quality_id);
|
||||
priv->signal_quality_id = 0;
|
||||
}
|
||||
|
||||
mm_gsm_creg_regex_destroy (priv->reg_regex);
|
||||
|
||||
g_free (priv->oper_code);
|
||||
|
@@ -133,6 +133,11 @@ void mm_generic_gsm_update_allowed_mode (MMGenericGsm *modem,
|
||||
void mm_generic_gsm_update_access_technology (MMGenericGsm *modem,
|
||||
MMModemGsmAccessTech act);
|
||||
|
||||
/* Called to asynchronously update the current signal quality of the device;
|
||||
* 'quality' is a 0 - 100% quality.
|
||||
*/
|
||||
void mm_generic_gsm_update_signal_quality (MMGenericGsm *modem, guint32 quality);
|
||||
|
||||
void mm_generic_gsm_check_pin (MMGenericGsm *modem,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
@@ -205,22 +205,22 @@ mm_gsm_destroy_scan_data (gpointer data)
|
||||
/*************************************************************************/
|
||||
|
||||
/* +CREG: <stat> (GSM 07.07 CREG=1 unsolicited) */
|
||||
#define CREG1 "\\+CG?REG:\\s*(\\d{1})"
|
||||
#define CREG1 "\\+(CREG|CGREG):\\s*(\\d{1})"
|
||||
|
||||
/* +CREG: <n>,<stat> (GSM 07.07 CREG=1 solicited) */
|
||||
#define CREG2 "\\+CG?REG:\\s*(\\d{1}),\\s*(\\d{1})"
|
||||
#define CREG2 "\\+(CREG|CGREG):\\s*(\\d{1}),\\s*(\\d{1})"
|
||||
|
||||
/* +CREG: <stat>,<lac>,<ci> (GSM 07.07 CREG=2 unsolicited) */
|
||||
#define CREG3 "\\+CG?REG:\\s*(\\d{1}),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)"
|
||||
#define CREG3 "\\+(CREG|CGREG):\\s*(\\d{1}),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)"
|
||||
|
||||
/* +CREG: <n>,<stat>,<lac>,<ci> (GSM 07.07 solicited and some CREG=2 unsolicited) */
|
||||
#define CREG4 "\\+CG?REG:\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)"
|
||||
#define CREG4 "\\+(CREG|CGREG):\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)"
|
||||
|
||||
/* +CREG: <stat>,<lac>,<ci>,<AcT> (ETSI 27.007 CREG=2 unsolicited) */
|
||||
#define CREG5 "\\+CG?REG:\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})"
|
||||
#define CREG5 "\\+(CREG|CGREG):\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})"
|
||||
|
||||
/* +CREG: <n>,<stat>,<lac>,<ci>,<AcT> (ETSI 27.007 solicited and some CREG=2 unsolicited) */
|
||||
#define CREG6 "\\+CG?REG:\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})"
|
||||
#define CREG6 "\\+(CREG|CGREG):\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})"
|
||||
|
||||
GPtrArray *
|
||||
mm_gsm_creg_regex_get (gboolean solicited)
|
||||
@@ -319,7 +319,7 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
|
||||
gulong *out_lac,
|
||||
gulong *out_ci,
|
||||
gint *out_act,
|
||||
gboolean *out_greg,
|
||||
gboolean *out_cgreg,
|
||||
GError **error)
|
||||
{
|
||||
gboolean success = FALSE, foo;
|
||||
@@ -327,56 +327,60 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
|
||||
gulong stat = 0, lac = 0, ci = 0;
|
||||
guint istat = 0, ilac = 0, ici = 0, iact = 0;
|
||||
char *str;
|
||||
const char *orig_str;
|
||||
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
g_return_val_if_fail (out_reg_state != NULL, FALSE);
|
||||
g_return_val_if_fail (out_lac != NULL, FALSE);
|
||||
g_return_val_if_fail (out_ci != NULL, FALSE);
|
||||
g_return_val_if_fail (out_act != NULL, FALSE);
|
||||
g_return_val_if_fail (out_greg != NULL, FALSE);
|
||||
g_return_val_if_fail (out_cgreg != NULL, FALSE);
|
||||
|
||||
str = g_match_info_fetch (info, 1);
|
||||
if (str && strstr (str, "CGREG"))
|
||||
*out_cgreg = TRUE;
|
||||
|
||||
/* Normally the number of matches could be used to determine what each
|
||||
* item is, but we have overlap in one case.
|
||||
*/
|
||||
n_matches = g_match_info_get_match_count (info);
|
||||
if (n_matches == 2) {
|
||||
if (n_matches == 3) {
|
||||
/* CREG=1: +CREG: <stat> */
|
||||
istat = 1;
|
||||
} else if (n_matches == 3) {
|
||||
/* Solicited response: +CREG: <n>,<stat> */
|
||||
istat = 2;
|
||||
} else if (n_matches == 4) {
|
||||
/* CREG=2 (GSM 07.07): +CREG: <stat>,<lac>,<ci> */
|
||||
istat = 1;
|
||||
ilac = 2;
|
||||
ici = 3;
|
||||
/* Solicited response: +CREG: <n>,<stat> */
|
||||
istat = 3;
|
||||
} else if (n_matches == 5) {
|
||||
/* CREG=2 (GSM 07.07): +CREG: <stat>,<lac>,<ci> */
|
||||
istat = 2;
|
||||
ilac = 3;
|
||||
ici = 4;
|
||||
} else if (n_matches == 6) {
|
||||
/* CREG=2 (ETSI 27.007): +CREG: <stat>,<lac>,<ci>,<AcT>
|
||||
* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>
|
||||
*/
|
||||
|
||||
/* To distinguish, check length of the second match item. If it's
|
||||
* more than one digit or has quotes in it, then we have the first format.
|
||||
/* To distinguish, check length of the third match item. If it's
|
||||
* more than one digit or has quotes in it then it's a LAC and we
|
||||
* got the first format.
|
||||
*/
|
||||
str = g_match_info_fetch (info, 2);
|
||||
str = g_match_info_fetch (info, 3);
|
||||
if (str && (strchr (str, '"') || strlen (str) > 1)) {
|
||||
g_free (str);
|
||||
istat = 1;
|
||||
ilac = 2;
|
||||
ici = 3;
|
||||
iact = 4;
|
||||
} else {
|
||||
istat = 2;
|
||||
ilac = 3;
|
||||
ici = 4;
|
||||
iact = 5;
|
||||
} else {
|
||||
istat = 3;
|
||||
ilac = 4;
|
||||
ici = 5;
|
||||
}
|
||||
} else if (n_matches == 6) {
|
||||
} else if (n_matches == 7) {
|
||||
/* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>,<AcT> */
|
||||
istat = 2;
|
||||
ilac = 3;
|
||||
ici = 4;
|
||||
iact = 5;
|
||||
istat = 3;
|
||||
ilac = 4;
|
||||
ici = 5;
|
||||
iact = 6;
|
||||
}
|
||||
|
||||
/* Status */
|
||||
@@ -416,9 +420,6 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
|
||||
act = -1;
|
||||
}
|
||||
|
||||
orig_str = g_match_info_get_string (info);
|
||||
*out_greg = !!strstr (orig_str, "+CGREG");
|
||||
|
||||
*out_reg_state = (guint32) stat;
|
||||
if (stat != 4) {
|
||||
/* Don't fill in lac/ci/act if the device's state is unknown */
|
||||
|
@@ -36,7 +36,7 @@ gboolean mm_gsm_parse_creg_response (GMatchInfo *info,
|
||||
gulong *out_lac,
|
||||
gulong *out_ci,
|
||||
gint *out_act,
|
||||
gboolean *out_greg,
|
||||
gboolean *out_cgreg,
|
||||
GError **error);
|
||||
|
||||
#endif /* MM_MODEM_HELPERS_H */
|
||||
|
@@ -321,8 +321,14 @@ real_config_fd (MMSerialPort *self, int fd, GError **error)
|
||||
stbuf.c_cc[VTIME] = 0;
|
||||
stbuf.c_cc[VEOF] = 1;
|
||||
|
||||
stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB);
|
||||
stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits);
|
||||
/* Use software handshaking */
|
||||
stbuf.c_iflag |= (IXON | IXOFF | IXANY);
|
||||
|
||||
/* Set up port speed and serial attributes; also ignore modem control
|
||||
* lines since most drivers don't implement RTS/CTS anyway.
|
||||
*/
|
||||
stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARENB | CRTSCTS);
|
||||
stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits | CLOCAL);
|
||||
|
||||
if (ioctl (fd, TCSETA, &stbuf) < 0) {
|
||||
g_set_error (error,
|
||||
|
@@ -670,6 +670,25 @@ test_cgreg2_f3607gw_unsolicited (void *f, gpointer d)
|
||||
test_creg_match ("Ericsson F3607gw CGREG=2", FALSE, reply, data, &result);
|
||||
}
|
||||
|
||||
static void
|
||||
test_creg_cgreg_multi_unsolicited (void *f, gpointer d)
|
||||
{
|
||||
TestData *data = (TestData *) d;
|
||||
const char *reply = "\r\n+CREG: 5\r\n\r\n+CGREG: 0\r\n";
|
||||
const CregResult result = { 5, 0, 0, -1, 1, FALSE};
|
||||
|
||||
test_creg_match ("Multi CREG/CGREG", FALSE, reply, data, &result);
|
||||
}
|
||||
|
||||
static void
|
||||
test_creg_cgreg_multi2_unsolicited (void *f, gpointer d)
|
||||
{
|
||||
TestData *data = (TestData *) d;
|
||||
const char *reply = "\r\n+CGREG: 0\r\n\r\n+CREG: 5\r\n";
|
||||
const CregResult result = { 0, 0, 0, -1, 1, TRUE};
|
||||
|
||||
test_creg_match ("Multi CREG/CGREG #2", FALSE, reply, data, &result);
|
||||
}
|
||||
|
||||
static TestData *
|
||||
test_data_new (void)
|
||||
@@ -753,6 +772,9 @@ int main (int argc, char **argv)
|
||||
g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_solicited, data));
|
||||
g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_unsolicited, data));
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi_unsolicited, data));
|
||||
g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi2_unsolicited, data));
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
test_data_free (data);
|
||||
|
Reference in New Issue
Block a user