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-gsm-sms.xml \
|
||||||
mm-modem-simple.xml \
|
mm-modem-simple.xml \
|
||||||
mm-serial-error.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-network.xml"/>
|
||||||
<xi:include href="mm-modem-gsm-sms.xml"/>
|
<xi:include href="mm-modem-gsm-sms.xml"/>
|
||||||
<xi:include href="mm-modem-gsm-hso.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-serial-error.xml"/>
|
||||||
<xi:include href="mm-modem-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 {
|
typedef struct {
|
||||||
/* Cached state */
|
/* Cached state */
|
||||||
guint signal_quality;
|
|
||||||
MMModemGsmBand band;
|
MMModemGsmBand band;
|
||||||
} MMModemHuaweiGsmPrivate;
|
} 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 */
|
/* Unsolicited message handlers */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -400,24 +376,22 @@ handle_signal_quality_change (MMAtSerialPort *port,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (user_data);
|
MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (user_data);
|
||||||
MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self);
|
|
||||||
char *str;
|
char *str;
|
||||||
int quality;
|
int quality = 0;
|
||||||
|
|
||||||
str = g_match_info_fetch (match_info, 1);
|
str = g_match_info_fetch (match_info, 1);
|
||||||
quality = atoi (str);
|
quality = atoi (str);
|
||||||
g_free (str);
|
g_free (str);
|
||||||
|
|
||||||
if (quality == 99)
|
if (quality == 99) {
|
||||||
/* 99 means unknown */
|
/* 99 means unknown */
|
||||||
quality = 0;
|
quality = 0;
|
||||||
else
|
} else {
|
||||||
/* Normalize the quality */
|
/* Normalize the quality */
|
||||||
quality = quality * 100 / 31;
|
quality = CLAMP (quality, 0, 31) * 100 / 31;
|
||||||
|
}
|
||||||
|
|
||||||
g_debug ("Signal quality: %d", quality);
|
mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (self), (guint32) quality);
|
||||||
priv->signal_quality = (guint32) quality;
|
|
||||||
mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (self), (guint32) quality);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -568,7 +542,6 @@ modem_gsm_network_init (MMModemGsmNetwork *class)
|
|||||||
{
|
{
|
||||||
class->set_band = set_band;
|
class->set_band = set_band;
|
||||||
class->get_band = get_band;
|
class->get_band = get_band;
|
||||||
class->get_signal_quality = get_signal_quality;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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_2G 5
|
||||||
#define MBM_NETWORK_MODE_3G 6
|
#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 {
|
typedef struct {
|
||||||
guint reg_id;
|
guint reg_id;
|
||||||
gboolean have_emrdy;
|
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);
|
primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
|
||||||
g_assert (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 = g_type_interface_peek_parent (MM_MODEM_GSM_NETWORK_GET_INTERFACE (self));
|
||||||
parent_modem_iface->do_register (MM_MODEM_GSM_NETWORK (self),
|
parent_modem_iface->do_register (MM_MODEM_GSM_NETWORK (self),
|
||||||
reg_data->network_id,
|
reg_data->network_id,
|
||||||
@@ -214,57 +206,47 @@ set_allowed_mode (MMGenericGsm *gsm,
|
|||||||
g_free (command);
|
g_free (command);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void
|
static void
|
||||||
get_network_mode_done (MMAtSerialPort *port,
|
mbm_erinfo_received (MMAtSerialPort *port,
|
||||||
GString *response,
|
GMatchInfo *info,
|
||||||
GError *error,
|
gpointer user_data)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
|
||||||
char *erinfo;
|
char *str;
|
||||||
int mode = 0, gsm = 0, umts = 0;
|
|
||||||
gboolean parsed = FALSE;
|
|
||||||
|
|
||||||
if (error) {
|
str = g_match_info_fetch (info, 2);
|
||||||
info->error = g_error_copy (error);
|
if (str) {
|
||||||
goto done;
|
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:");
|
/* 3G modes take precedence */
|
||||||
if (!erinfo)
|
str = g_match_info_fetch (info, 3);
|
||||||
goto done;
|
if (str) {
|
||||||
|
switch (atoi (str)) {
|
||||||
if (sscanf (erinfo + 8, "%d,%d,%d", &mode, &gsm, &umts) != 3)
|
case 1:
|
||||||
goto done;
|
act = MM_MODEM_GSM_ACCESS_TECH_UMTS;
|
||||||
|
break;
|
||||||
if (gsm || umts) {
|
case 2:
|
||||||
MMModemGsmMode mm_mode = MM_MODEM_GSM_MODE_ANY;
|
act = MM_MODEM_GSM_ACCESS_TECH_HSDPA;
|
||||||
|
break;
|
||||||
if (gsm == MBM_ERINFO_2G_GPRS)
|
default:
|
||||||
mm_mode = MM_MODEM_GSM_MODE_GPRS;
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
done:
|
mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (user_data), act);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_allowed_mode_done (MMAtSerialPort *port,
|
get_allowed_mode_done (MMAtSerialPort *port,
|
||||||
@@ -364,6 +346,10 @@ mbm_enable_done (MMAtSerialPort *port,
|
|||||||
{
|
{
|
||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
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);
|
mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,10 +442,10 @@ typedef struct {
|
|||||||
} DisableInfo;
|
} DisableInfo;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
disable_creg_cmer_done (MMAtSerialPort *port,
|
disable_unsolicited_done (MMAtSerialPort *port,
|
||||||
GString *response,
|
GString *response,
|
||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
|
|
||||||
{
|
{
|
||||||
MMModem *parent_modem_iface;
|
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);
|
primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
|
||||||
g_assert (primary);
|
g_assert (primary);
|
||||||
|
|
||||||
/* Turn off unsolicited +CIEV signal strength indicator */
|
/* Turn off unsolicited responses */
|
||||||
mm_at_serial_port_queue_command (primary, "+CREG=0;+CMER=0", 5, disable_creg_cmer_done, info);
|
mm_at_serial_port_queue_command (primary, "+CMER=0;*ERINFO=0", 5, disable_unsolicited_done, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -551,18 +537,20 @@ mbm_ciev_received (MMAtSerialPort *port,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
int quality = 0, ind = 0;
|
int quality = 0, ind = 0;
|
||||||
const char *str;
|
char *str;
|
||||||
|
|
||||||
str = g_match_info_fetch (info, 1);
|
str = g_match_info_fetch (info, 1);
|
||||||
if (str)
|
if (str)
|
||||||
ind = atoi (str);
|
ind = atoi (str);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
if (ind == MBM_SIGNAL_INDICATOR) {
|
if (ind == MBM_SIGNAL_INDICATOR) {
|
||||||
str = g_match_info_fetch (info, 2);
|
str = g_match_info_fetch (info, 2);
|
||||||
if (str) {
|
if (str) {
|
||||||
quality = atoi (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)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
int state = 0;
|
int state = 0;
|
||||||
const char *str;
|
char *str;
|
||||||
|
|
||||||
str = g_match_info_fetch (info, 1);
|
str = g_match_info_fetch (info, 1);
|
||||||
if (str)
|
if (str)
|
||||||
state = atoi (str);
|
state = atoi (str);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
if (MBM_E2NAP_DISCONNECTED == state) {
|
if (MBM_E2NAP_DISCONNECTED == state) {
|
||||||
g_debug ("%s: disconnected", __func__);
|
g_debug ("%s: disconnected", __func__);
|
||||||
@@ -791,17 +780,19 @@ grab_port (MMModem *modem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
|
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;
|
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);
|
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);
|
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_emrdy_received, modem, NULL);
|
||||||
g_regex_unref (regex);
|
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);
|
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);
|
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_pacsp_received, modem, NULL);
|
||||||
g_regex_unref (regex);
|
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 */
|
/* 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);
|
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);
|
g_regex_unref (regex);
|
||||||
|
|
||||||
regex = g_regex_new ("\\r\\n\\*EMWI: (\\d),(\\d).*\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
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);
|
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL);
|
||||||
g_regex_unref (regex);
|
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;
|
return TRUE;
|
||||||
|
@@ -48,13 +48,27 @@ mm_modem_novatel_gsm_new (const char *device,
|
|||||||
/* Modem class override functions */
|
/* 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
|
static void
|
||||||
dmat_callback (MMAtSerialPort *port,
|
dmat_callback (MMAtSerialPort *port,
|
||||||
GString *response,
|
GString *response,
|
||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
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
|
static gboolean
|
||||||
|
@@ -52,6 +52,39 @@ mm_modem_zte_new (const char *device,
|
|||||||
NULL));
|
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 */
|
/* Modem class override functions */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -223,8 +256,8 @@ grab_port (MMModem *modem,
|
|||||||
g_regex_unref (regex);
|
g_regex_unref (regex);
|
||||||
|
|
||||||
/* Current network and service domain */
|
/* Current network and service domain */
|
||||||
regex = g_regex_new ("\\r\\n\\+ZPASR: (.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, 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, NULL, NULL, 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);
|
g_regex_unref (regex);
|
||||||
|
|
||||||
/* SIM request to Build Main Menu */
|
/* SIM request to Build Main Menu */
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <dbus/dbus-glib.h>
|
#include <dbus/dbus-glib.h>
|
||||||
#include <dbus/dbus-glib-lowlevel.h>
|
#include <dbus/dbus-glib-lowlevel.h>
|
||||||
#include "mm-manager.h"
|
#include "mm-manager.h"
|
||||||
@@ -33,8 +34,11 @@ mm_signal_handler (int signo)
|
|||||||
mm_options_set_debug (!mm_options_debug ());
|
mm_options_set_debug (!mm_options_debug ());
|
||||||
else if (signo == SIGINT || signo == SIGTERM) {
|
else if (signo == SIGINT || signo == SIGTERM) {
|
||||||
g_message ("Caught signal %d, shutting down...", signo);
|
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
|
static void
|
||||||
|
@@ -358,6 +358,9 @@ enable_all_done (MMModem *modem, GError *error, gpointer user_data)
|
|||||||
if (error)
|
if (error)
|
||||||
info->error = g_error_copy (error);
|
info->error = g_error_copy (error);
|
||||||
else {
|
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 */
|
/* Open up the second port, if one exists */
|
||||||
if (priv->secondary) {
|
if (priv->secondary) {
|
||||||
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &info->error)) {
|
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &info->error)) {
|
||||||
|
@@ -79,6 +79,8 @@ typedef struct {
|
|||||||
guint pending_reg_id;
|
guint pending_reg_id;
|
||||||
MMCallbackInfo *pending_reg_info;
|
MMCallbackInfo *pending_reg_info;
|
||||||
|
|
||||||
|
guint signal_quality_id;
|
||||||
|
time_t signal_quality_timestamp;
|
||||||
guint32 signal_quality;
|
guint32 signal_quality;
|
||||||
guint32 cid;
|
guint32 cid;
|
||||||
|
|
||||||
@@ -113,6 +115,17 @@ static gboolean handle_reg_status_response (MMGenericGsm *self,
|
|||||||
|
|
||||||
static MMModemGsmAccessTech etsi_act_to_mm_act (gint act);
|
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 *
|
MMModem *
|
||||||
mm_generic_gsm_new (const char *device,
|
mm_generic_gsm_new (const char *device,
|
||||||
const char *driver,
|
const char *driver,
|
||||||
@@ -145,14 +158,6 @@ mm_generic_gsm_get_cid (MMGenericGsm *modem)
|
|||||||
return MM_GENERIC_GSM_GET_PRIVATE (modem)->cid;
|
return MM_GENERIC_GSM_GET_PRIVATE (modem)->cid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
got_signal_quality (MMModem *modem,
|
|
||||||
guint32 result,
|
|
||||||
GError *error,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *result;
|
const char *result;
|
||||||
const char *normalized;
|
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 */
|
/* Get allowed mode */
|
||||||
if (MM_GENERIC_GSM_GET_CLASS (self)->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);
|
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);
|
info->error = mm_modem_check_removed (info->modem, error);
|
||||||
if (!info->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_serial_port_close (MM_SERIAL_PORT (port));
|
||||||
mm_modem_set_state (MM_MODEM (info->modem),
|
mm_modem_set_state (MM_MODEM (info->modem),
|
||||||
MM_MODEM_STATE_DISABLED,
|
MM_MODEM_STATE_DISABLED,
|
||||||
MM_MODEM_STATE_REASON_NONE);
|
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);
|
mm_callback_info_schedule (info);
|
||||||
}
|
}
|
||||||
@@ -903,11 +916,16 @@ disable (MMModem *modem,
|
|||||||
priv->poll_id = 0;
|
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[0] = 0;
|
||||||
priv->lac[1] = 0;
|
priv->lac[1] = 0;
|
||||||
priv->cell_id[0] = 0;
|
priv->cell_id[0] = 0;
|
||||||
priv->cell_id[1] = 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 */
|
/* Close the secondary port if its open */
|
||||||
if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
|
if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary)))
|
||||||
@@ -1268,6 +1286,49 @@ change_pin (MMModemGsmCard *modem,
|
|||||||
g_free (command);
|
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 *
|
static char *
|
||||||
parse_operator (const char *reply)
|
parse_operator (const char *reply)
|
||||||
{
|
{
|
||||||
@@ -1300,18 +1361,14 @@ read_operator_code_done (MMAtSerialPort *port,
|
|||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
|
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
||||||
char *oper;
|
char *oper;
|
||||||
|
|
||||||
if (error)
|
if (!error) {
|
||||||
return;
|
oper = parse_operator (response->str);
|
||||||
|
if (oper)
|
||||||
oper = parse_operator (response->str);
|
reg_info_updated (self, FALSE, 0, TRUE, oper, FALSE, NULL);
|
||||||
if (!oper)
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
g_free (priv->oper_code);
|
|
||||||
priv->oper_code = oper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1320,23 +1377,14 @@ read_operator_name_done (MMAtSerialPort *port,
|
|||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
|
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
||||||
char *oper;
|
char *oper;
|
||||||
|
|
||||||
if (error)
|
if (!error) {
|
||||||
return;
|
oper = parse_operator (response->str);
|
||||||
|
if (oper)
|
||||||
oper = parse_operator (response->str);
|
reg_info_updated (self, FALSE, 0, FALSE, NULL, TRUE, oper);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Registration */
|
/* 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
|
void
|
||||||
mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
|
mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
|
||||||
MMModemGsmNetworkRegStatus status)
|
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,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_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);
|
mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL);
|
||||||
} else {
|
} else
|
||||||
g_free (priv->oper_code);
|
reg_info_updated (MM_GENERIC_GSM (modem), FALSE, 0, TRUE, NULL, TRUE, NULL);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
mm_generic_gsm_update_enabled_state (modem, TRUE, MM_MODEM_STATE_REASON_NONE);
|
mm_generic_gsm_update_enabled_state (modem, TRUE, MM_MODEM_STATE_REASON_NONE);
|
||||||
}
|
}
|
||||||
@@ -1480,14 +1531,21 @@ reg_state_changed (MMAtSerialPort *port,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg_status_updated (self, state, NULL)) {
|
/* Don't update reg state on CGREG responses since for many devices it's
|
||||||
/* If registration is finished (either registered or failed) but the
|
* unclear what that registration state that actually reflects. We'll
|
||||||
* registration query hasn't completed yet, just remove the timeout and
|
* take CGREG registration state into account later when we have a more
|
||||||
* let the registration query complete.
|
* consistent way of handling it.
|
||||||
*/
|
*/
|
||||||
if (priv->pending_reg_id) {
|
if (cgreg == FALSE) {
|
||||||
g_source_remove (priv->pending_reg_id);
|
if (reg_status_updated (self, state, NULL)) {
|
||||||
priv->pending_reg_id = 0;
|
/* 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);
|
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);
|
info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NETWORK_TIMEOUT);
|
||||||
mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (info->modem));
|
mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (info->modem));
|
||||||
@@ -2133,26 +2195,91 @@ set_apn (MMModemGsmNetwork *modem,
|
|||||||
|
|
||||||
/* GetSignalQuality */
|
/* 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
|
static void
|
||||||
get_signal_quality_done (MMAtSerialPort *port,
|
get_signal_quality_done (MMAtSerialPort *port,
|
||||||
GString *response,
|
GString *response,
|
||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MMGenericGsmPrivate *priv;
|
|
||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
char *reply = response->str;
|
char *reply = response->str;
|
||||||
|
gboolean parsed = FALSE;
|
||||||
|
|
||||||
if (error)
|
info->error = mm_modem_check_removed (info->modem, error);
|
||||||
info->error = g_error_copy (error);
|
if (info->error)
|
||||||
else if (!strncmp (reply, "+CSQ: ", 6)) {
|
goto done;
|
||||||
|
|
||||||
|
if (!strncmp (reply, "+CSQ: ", 6)) {
|
||||||
/* Got valid reply */
|
/* Got valid reply */
|
||||||
int quality;
|
int quality;
|
||||||
int ber;
|
int ber;
|
||||||
|
|
||||||
reply += 6;
|
if (sscanf (reply + 6, "%d, %d", &quality, &ber)) {
|
||||||
|
|
||||||
if (sscanf (reply, "%d, %d", &quality, &ber)) {
|
|
||||||
/* 99 means unknown */
|
/* 99 means unknown */
|
||||||
if (quality == 99) {
|
if (quality == 99) {
|
||||||
info->error = g_error_new_literal (MM_MOBILE_ERROR,
|
info->error = g_error_new_literal (MM_MOBILE_ERROR,
|
||||||
@@ -2162,15 +2289,19 @@ get_signal_quality_done (MMAtSerialPort *port,
|
|||||||
/* Normalize the quality */
|
/* Normalize the quality */
|
||||||
quality = CLAMP (quality, 0, 31) * 100 / 31;
|
quality = CLAMP (quality, 0, 31) * 100 / 31;
|
||||||
|
|
||||||
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
|
mm_generic_gsm_update_signal_quality (MM_GENERIC_GSM (info->modem), quality);
|
||||||
priv->signal_quality = quality;
|
|
||||||
mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
|
mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
|
||||||
}
|
}
|
||||||
} else
|
parsed = TRUE;
|
||||||
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
}
|
||||||
"Could not parse signal quality results");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
mm_callback_info_schedule (info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2185,7 +2316,6 @@ get_signal_quality (MMModemGsmNetwork *modem,
|
|||||||
|
|
||||||
connected = mm_port_get_connected (MM_PORT (priv->primary));
|
connected = mm_port_get_connected (MM_PORT (priv->primary));
|
||||||
if (connected && !priv->secondary) {
|
if (connected && !priv->secondary) {
|
||||||
g_message ("Returning saved signal quality %d", priv->signal_quality);
|
|
||||||
callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data);
|
callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2221,19 +2351,19 @@ etsi_act_to_mm_act (gint act)
|
|||||||
while (iter->mm_act != MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) {
|
while (iter->mm_act != MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) {
|
||||||
if (iter->etsi_act == act)
|
if (iter->etsi_act == act)
|
||||||
return iter->mm_act;
|
return iter->mm_act;
|
||||||
|
iter++;
|
||||||
}
|
}
|
||||||
return MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
|
return MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
mm_generic_gsm_update_access_technology (MMGenericGsm *modem,
|
_internal_update_access_technology (MMGenericGsm *modem,
|
||||||
MMModemGsmAccessTech act)
|
MMModemGsmAccessTech act)
|
||||||
{
|
{
|
||||||
MMGenericGsmPrivate *priv;
|
MMGenericGsmPrivate *priv;
|
||||||
|
|
||||||
g_return_if_fail (modem != NULL);
|
g_return_if_fail (modem != NULL);
|
||||||
g_return_if_fail (MM_IS_GENERIC_GSM (modem));
|
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);
|
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);
|
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
|
void
|
||||||
mm_generic_gsm_update_allowed_mode (MMGenericGsm *self,
|
mm_generic_gsm_update_allowed_mode (MMGenericGsm *self,
|
||||||
MMModemGsmAllowedMode mode)
|
MMModemGsmAllowedMode mode)
|
||||||
@@ -2509,8 +2651,6 @@ simple_connect (MMModemSimple *simple,
|
|||||||
simple_state_machine (MM_MODEM (simple), NULL, info);
|
simple_state_machine (MM_MODEM (simple), NULL, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
simple_free_gvalue (gpointer data)
|
simple_free_gvalue (gpointer data)
|
||||||
{
|
{
|
||||||
@@ -2542,16 +2682,39 @@ simple_string_value (const char *str)
|
|||||||
return val;
|
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
|
static void
|
||||||
simple_status_got_signal_quality (MMModem *modem,
|
simple_status_got_signal_quality (MMModem *modem,
|
||||||
guint32 result,
|
guint32 result,
|
||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
if (error)
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
g_warning ("Error getting signal quality: %s", error->message);
|
GHashTable *properties;
|
||||||
else
|
|
||||||
g_hash_table_insert ((GHashTable *) user_data, "signal_quality", simple_uint_value (result));
|
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
|
static void
|
||||||
@@ -2560,9 +2723,14 @@ simple_status_got_band (MMModem *modem,
|
|||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
/* Ignore band errors since there's no generic implementation for it */
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
if (!error)
|
GHashTable *properties;
|
||||||
g_hash_table_insert ((GHashTable *) user_data, "band", simple_uint_value (result));
|
|
||||||
|
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
|
static void
|
||||||
@@ -2576,17 +2744,15 @@ simple_status_got_reg_info (MMModemGsmNetwork *modem,
|
|||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
GHashTable *properties;
|
GHashTable *properties;
|
||||||
|
|
||||||
if (error)
|
info->error = mm_modem_check_removed ((MMModem *) modem, error);
|
||||||
info->error = g_error_copy (error);
|
if (!info->error) {
|
||||||
else {
|
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
|
||||||
properties = (GHashTable *) mm_callback_info_get_data (info, "simple-get-status");
|
|
||||||
|
|
||||||
g_hash_table_insert (properties, "registration_status", simple_uint_value (status));
|
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_code", simple_string_value (oper_code));
|
||||||
g_hash_table_insert (properties, "operator_name", simple_string_value (oper_name));
|
g_hash_table_insert (properties, "operator_name", simple_string_value (oper_name));
|
||||||
}
|
}
|
||||||
|
simple_status_complete_item (info);
|
||||||
mm_callback_info_schedule (info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2595,7 +2761,7 @@ simple_get_status_invoke (MMCallbackInfo *info)
|
|||||||
MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback;
|
MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback;
|
||||||
|
|
||||||
callback (MM_MODEM_SIMPLE (info->modem),
|
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);
|
info->error, info->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2615,12 +2781,15 @@ simple_get_status (MMModemSimple *simple,
|
|||||||
G_CALLBACK (callback),
|
G_CALLBACK (callback),
|
||||||
user_data);
|
user_data);
|
||||||
|
|
||||||
properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, simple_free_gvalue);
|
properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, simple_free_gvalue);
|
||||||
mm_callback_info_set_data (info, "simple-get-status", properties, (GDestroyNotify) g_hash_table_unref);
|
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_signal_quality (gsm, simple_status_got_signal_quality, info);
|
||||||
mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties);
|
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, properties);
|
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) {
|
if (priv->act > -1) {
|
||||||
/* Deprecated key */
|
/* Deprecated key */
|
||||||
@@ -2791,6 +2960,11 @@ finalize (GObject *object)
|
|||||||
priv->poll_id = 0;
|
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);
|
mm_gsm_creg_regex_destroy (priv->reg_regex);
|
||||||
|
|
||||||
g_free (priv->oper_code);
|
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,
|
void mm_generic_gsm_update_access_technology (MMGenericGsm *modem,
|
||||||
MMModemGsmAccessTech act);
|
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,
|
void mm_generic_gsm_check_pin (MMGenericGsm *modem,
|
||||||
MMModemFn callback,
|
MMModemFn callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
@@ -205,22 +205,22 @@ mm_gsm_destroy_scan_data (gpointer data)
|
|||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
/* +CREG: <stat> (GSM 07.07 CREG=1 unsolicited) */
|
/* +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) */
|
/* +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) */
|
/* +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) */
|
/* +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) */
|
/* +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) */
|
/* +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 *
|
GPtrArray *
|
||||||
mm_gsm_creg_regex_get (gboolean solicited)
|
mm_gsm_creg_regex_get (gboolean solicited)
|
||||||
@@ -319,7 +319,7 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
|
|||||||
gulong *out_lac,
|
gulong *out_lac,
|
||||||
gulong *out_ci,
|
gulong *out_ci,
|
||||||
gint *out_act,
|
gint *out_act,
|
||||||
gboolean *out_greg,
|
gboolean *out_cgreg,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean success = FALSE, foo;
|
gboolean success = FALSE, foo;
|
||||||
@@ -327,56 +327,60 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
|
|||||||
gulong stat = 0, lac = 0, ci = 0;
|
gulong stat = 0, lac = 0, ci = 0;
|
||||||
guint istat = 0, ilac = 0, ici = 0, iact = 0;
|
guint istat = 0, ilac = 0, ici = 0, iact = 0;
|
||||||
char *str;
|
char *str;
|
||||||
const char *orig_str;
|
|
||||||
|
|
||||||
g_return_val_if_fail (info != NULL, FALSE);
|
g_return_val_if_fail (info != NULL, FALSE);
|
||||||
g_return_val_if_fail (out_reg_state != 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_lac != NULL, FALSE);
|
||||||
g_return_val_if_fail (out_ci != 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_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
|
/* Normally the number of matches could be used to determine what each
|
||||||
* item is, but we have overlap in one case.
|
* item is, but we have overlap in one case.
|
||||||
*/
|
*/
|
||||||
n_matches = g_match_info_get_match_count (info);
|
n_matches = g_match_info_get_match_count (info);
|
||||||
if (n_matches == 2) {
|
if (n_matches == 3) {
|
||||||
/* CREG=1: +CREG: <stat> */
|
/* CREG=1: +CREG: <stat> */
|
||||||
istat = 1;
|
|
||||||
} else if (n_matches == 3) {
|
|
||||||
/* Solicited response: +CREG: <n>,<stat> */
|
|
||||||
istat = 2;
|
istat = 2;
|
||||||
} else if (n_matches == 4) {
|
} else if (n_matches == 4) {
|
||||||
/* CREG=2 (GSM 07.07): +CREG: <stat>,<lac>,<ci> */
|
/* Solicited response: +CREG: <n>,<stat> */
|
||||||
istat = 1;
|
istat = 3;
|
||||||
ilac = 2;
|
|
||||||
ici = 3;
|
|
||||||
} else if (n_matches == 5) {
|
} 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 (ETSI 27.007): +CREG: <stat>,<lac>,<ci>,<AcT>
|
||||||
* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>
|
* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* To distinguish, check length of the second match item. If it's
|
/* To distinguish, check length of the third match item. If it's
|
||||||
* more than one digit or has quotes in it, then we have the first format.
|
* 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)) {
|
if (str && (strchr (str, '"') || strlen (str) > 1)) {
|
||||||
g_free (str);
|
g_free (str);
|
||||||
istat = 1;
|
|
||||||
ilac = 2;
|
|
||||||
ici = 3;
|
|
||||||
iact = 4;
|
|
||||||
} else {
|
|
||||||
istat = 2;
|
istat = 2;
|
||||||
ilac = 3;
|
ilac = 3;
|
||||||
ici = 4;
|
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> */
|
/* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>,<AcT> */
|
||||||
istat = 2;
|
istat = 3;
|
||||||
ilac = 3;
|
ilac = 4;
|
||||||
ici = 4;
|
ici = 5;
|
||||||
iact = 5;
|
iact = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status */
|
/* Status */
|
||||||
@@ -416,9 +420,6 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
|
|||||||
act = -1;
|
act = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
orig_str = g_match_info_get_string (info);
|
|
||||||
*out_greg = !!strstr (orig_str, "+CGREG");
|
|
||||||
|
|
||||||
*out_reg_state = (guint32) stat;
|
*out_reg_state = (guint32) stat;
|
||||||
if (stat != 4) {
|
if (stat != 4) {
|
||||||
/* Don't fill in lac/ci/act if the device's state is unknown */
|
/* 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_lac,
|
||||||
gulong *out_ci,
|
gulong *out_ci,
|
||||||
gint *out_act,
|
gint *out_act,
|
||||||
gboolean *out_greg,
|
gboolean *out_cgreg,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
#endif /* MM_MODEM_HELPERS_H */
|
#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[VTIME] = 0;
|
||||||
stbuf.c_cc[VEOF] = 1;
|
stbuf.c_cc[VEOF] = 1;
|
||||||
|
|
||||||
stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB);
|
/* Use software handshaking */
|
||||||
stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits);
|
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) {
|
if (ioctl (fd, TCSETA, &stbuf) < 0) {
|
||||||
g_set_error (error,
|
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);
|
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 *
|
static TestData *
|
||||||
test_data_new (void)
|
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_solicited, data));
|
||||||
g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_unsolicited, 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 ();
|
result = g_test_run ();
|
||||||
|
|
||||||
test_data_free (data);
|
test_data_free (data);
|
||||||
|
Reference in New Issue
Block a user