Merge remote branch 'origin/master' into qcdm
This commit is contained in:
+6
-2
@@ -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)) {
|
||||
|
||||
+266
-92
@@ -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);
|
||||
|
||||
+34
-33
@@ -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