gsm: implement location API
Depends on dbus-glib 0.86 + this patch: https://bugs.freedesktop.org/show_bug.cgi?id=28835 Still have to do the bits that allow plugins to add other location capabilities, but that can come later.
This commit is contained in:
@@ -35,18 +35,27 @@
|
||||
#include "mm-options.h"
|
||||
#include "mm-properties-changed-signal.h"
|
||||
#include "mm-utils.h"
|
||||
#if LOCATION_API
|
||||
#include "mm-modem-location.h"
|
||||
#endif
|
||||
|
||||
static void modem_init (MMModem *modem_class);
|
||||
static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class);
|
||||
static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class);
|
||||
static void modem_gsm_sms_init (MMModemGsmSms *gsm_sms_class);
|
||||
static void modem_simple_init (MMModemSimple *class);
|
||||
#if LOCATION_API
|
||||
static void modem_location_init (MMModemLocation *class);
|
||||
#endif
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMGenericGsm, mm_generic_gsm, MM_TYPE_MODEM_BASE, 0,
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_CARD, modem_gsm_card_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_SMS, modem_gsm_sms_init)
|
||||
#if LOCATION_API
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_LOCATION, modem_location_init)
|
||||
#endif
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init))
|
||||
|
||||
#define MM_GENERIC_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_GENERIC_GSM, MMGenericGsmPrivate))
|
||||
@@ -99,6 +108,11 @@ typedef struct {
|
||||
MMAtSerialPort *secondary;
|
||||
MMQcdmSerialPort *qcdm;
|
||||
MMPort *data;
|
||||
|
||||
/* Location API */
|
||||
guint32 loc_caps;
|
||||
gboolean loc_enabled;
|
||||
gboolean loc_signal;
|
||||
} MMGenericGsmPrivate;
|
||||
|
||||
static void get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info);
|
||||
@@ -139,6 +153,8 @@ static void reg_info_updated (MMGenericGsm *self,
|
||||
gboolean update_name,
|
||||
const char *oper_name);
|
||||
|
||||
static void update_lac_ci (MMGenericGsm *self, gulong lac, gulong ci, guint idx);
|
||||
|
||||
MMModem *
|
||||
mm_generic_gsm_new (const char *device,
|
||||
const char *driver,
|
||||
@@ -309,9 +325,10 @@ get_imei_cb (MMModem *modem,
|
||||
/*****************************************************************************/
|
||||
|
||||
static MMModemGsmNetworkRegStatus
|
||||
gsm_reg_status (MMGenericGsm *self)
|
||||
gsm_reg_status (MMGenericGsm *self, guint32 *out_idx)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
guint32 idx = 1;
|
||||
|
||||
/* Some devices (Blackberries for example) will respond to +CGREG, but
|
||||
* return ERROR for +CREG, probably because their firmware is just stupid.
|
||||
@@ -320,23 +337,36 @@ gsm_reg_status (MMGenericGsm *self)
|
||||
*/
|
||||
|
||||
if ( priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
||||
|| priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)
|
||||
return priv->reg_status[0];
|
||||
|| priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
|
||||
idx = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
||||
|| priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)
|
||||
return priv->reg_status[1];
|
||||
|| priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
|
||||
idx = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING)
|
||||
return priv->reg_status[0];
|
||||
if (priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING) {
|
||||
idx = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING)
|
||||
return priv->reg_status[1];
|
||||
if (priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING) {
|
||||
idx = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->reg_status[0] != MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN)
|
||||
return priv->reg_status[0];
|
||||
if (priv->reg_status[0] != MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN) {
|
||||
idx = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return priv->reg_status[1];
|
||||
out:
|
||||
if (out_idx)
|
||||
*out_idx = idx;
|
||||
return priv->reg_status[idx];
|
||||
}
|
||||
|
||||
void
|
||||
@@ -350,7 +380,7 @@ mm_generic_gsm_update_enabled_state (MMGenericGsm *self,
|
||||
if (stay_connected && (mm_modem_get_state (MM_MODEM (self)) >= MM_MODEM_STATE_DISCONNECTING))
|
||||
return;
|
||||
|
||||
switch (gsm_reg_status (self)) {
|
||||
switch (gsm_reg_status (self, NULL)) {
|
||||
case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
|
||||
case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
|
||||
mm_modem_set_state (MM_MODEM (self), MM_MODEM_STATE_REGISTERED, reason);
|
||||
@@ -614,6 +644,20 @@ release_port (MMModem *modem, const char *subsys, const char *name)
|
||||
check_valid (MM_GENERIC_GSM (modem));
|
||||
}
|
||||
|
||||
#if LOCATION_API
|
||||
static void
|
||||
add_loc_capability (MMGenericGsm *self, guint32 cap)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
guint32 old_caps = priv->loc_caps;
|
||||
|
||||
priv->loc_caps |= cap;
|
||||
if (priv->loc_caps != old_caps) {
|
||||
g_object_notify (G_OBJECT (self), MM_MODEM_LOCATION_CAPABILITIES);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
reg_poll_response (MMAtSerialPort *port,
|
||||
GString *response,
|
||||
@@ -711,6 +755,10 @@ cgreg2_done (MMAtSerialPort *port,
|
||||
/* Try CGREG=1 instead */
|
||||
mm_at_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info);
|
||||
} else {
|
||||
#if LOCATION_API
|
||||
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
|
||||
#endif
|
||||
|
||||
/* Success; get initial state */
|
||||
mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem);
|
||||
|
||||
@@ -767,6 +815,10 @@ creg2_done (MMAtSerialPort *port,
|
||||
g_clear_error (&info->error);
|
||||
mm_at_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info);
|
||||
} else {
|
||||
#if LOCATION_API
|
||||
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
|
||||
#endif
|
||||
|
||||
/* Success; get initial state */
|
||||
mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem);
|
||||
|
||||
@@ -1170,10 +1222,8 @@ disable (MMModem *modem,
|
||||
priv->pin_check_timeout = 0;
|
||||
}
|
||||
|
||||
priv->lac[0] = 0;
|
||||
priv->lac[1] = 0;
|
||||
priv->cell_id[0] = 0;
|
||||
priv->cell_id[1] = 0;
|
||||
update_lac_ci (self, 0, 0, 0);
|
||||
update_lac_ci (self, 0, 0, 1);
|
||||
_internal_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
|
||||
|
||||
/* Close the secondary port if its open */
|
||||
@@ -1634,9 +1684,9 @@ reg_info_updated (MMGenericGsm *self,
|
||||
g_return_if_fail ( rs_type == MM_GENERIC_GSM_REG_TYPE_CS
|
||||
|| rs_type == MM_GENERIC_GSM_REG_TYPE_PS);
|
||||
|
||||
old_status = gsm_reg_status (self);
|
||||
old_status = gsm_reg_status (self, NULL);
|
||||
priv->reg_status[rs_type - 1] = status;
|
||||
if (gsm_reg_status (self) != old_status)
|
||||
if (gsm_reg_status (self, NULL) != old_status)
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
@@ -1658,7 +1708,7 @@ reg_info_updated (MMGenericGsm *self,
|
||||
|
||||
if (changed) {
|
||||
mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (self),
|
||||
gsm_reg_status (self),
|
||||
gsm_reg_status (self, NULL),
|
||||
priv->oper_code,
|
||||
priv->oper_name);
|
||||
}
|
||||
@@ -1948,7 +1998,7 @@ reg_state_changed (MMAtSerialPort *port,
|
||||
{
|
||||
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
guint32 state = 0, idx;
|
||||
guint32 state = 0;
|
||||
gulong lac = 0, cell_id = 0;
|
||||
gint act = -1;
|
||||
gboolean cgreg = FALSE;
|
||||
@@ -1974,9 +2024,7 @@ reg_state_changed (MMAtSerialPort *port,
|
||||
}
|
||||
}
|
||||
|
||||
idx = cgreg ? 1 : 0;
|
||||
priv->lac[idx] = lac;
|
||||
priv->cell_id[idx] = cell_id;
|
||||
update_lac_ci (self, lac, cell_id, cgreg ? 1 : 0);
|
||||
|
||||
/* Only update access technology if it appeared in the CREG/CGREG response */
|
||||
if (act != -1)
|
||||
@@ -2014,7 +2062,7 @@ handle_reg_status_response (MMGenericGsm *self,
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
GMatchInfo *match_info;
|
||||
guint32 status = 0, idx;
|
||||
guint32 status = 0;
|
||||
gulong lac = 0, ci = 0;
|
||||
gint act = -1;
|
||||
gboolean cgreg = FALSE;
|
||||
@@ -2043,9 +2091,7 @@ handle_reg_status_response (MMGenericGsm *self,
|
||||
}
|
||||
|
||||
/* Success; update cached location information */
|
||||
idx = cgreg ? 1 : 0;
|
||||
priv->lac[idx] = lac;
|
||||
priv->cell_id[idx] = ci;
|
||||
update_lac_ci (self, lac, ci, cgreg ? 1 : 0);
|
||||
|
||||
/* Only update access technology if it appeared in the CREG/CGREG response */
|
||||
if (act != -1)
|
||||
@@ -2108,7 +2154,7 @@ get_reg_status_done (MMAtSerialPort *port,
|
||||
goto reg_done;
|
||||
}
|
||||
|
||||
status = gsm_reg_status (self);
|
||||
status = gsm_reg_status (self, NULL);
|
||||
if ( status != MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
||||
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING
|
||||
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED) {
|
||||
@@ -2222,7 +2268,7 @@ do_register (MMModemGsmNetwork *modem,
|
||||
if (network_id) {
|
||||
command = g_strdup_printf ("+COPS=1,2,\"%s\"", network_id);
|
||||
priv->manual_reg = TRUE;
|
||||
} else if (reg_is_idle (gsm_reg_status (self)) || priv->manual_reg) {
|
||||
} else if (reg_is_idle (gsm_reg_status (self, NULL)) || priv->manual_reg) {
|
||||
command = g_strdup ("+COPS=0,,");
|
||||
priv->manual_reg = FALSE;
|
||||
}
|
||||
@@ -2260,7 +2306,7 @@ gsm_network_reg_info_invoke (MMCallbackInfo *info)
|
||||
MMModemGsmNetworkRegInfoFn callback = (MMModemGsmNetworkRegInfoFn) info->callback;
|
||||
|
||||
callback (MM_MODEM_GSM_NETWORK (info->modem),
|
||||
gsm_reg_status (MM_GENERIC_GSM (info->modem)),
|
||||
gsm_reg_status (MM_GENERIC_GSM (info->modem), NULL),
|
||||
priv->oper_code,
|
||||
priv->oper_name,
|
||||
info->error,
|
||||
@@ -3564,7 +3610,7 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data)
|
||||
priv->roam_allowed = !home_only;
|
||||
|
||||
/* Don't connect if we're not supposed to be roaming */
|
||||
status = gsm_reg_status (MM_GENERIC_GSM (modem));
|
||||
status = gsm_reg_status (MM_GENERIC_GSM (modem), NULL);
|
||||
if (home_only && (status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)) {
|
||||
info->error = g_error_new_literal (MM_MOBILE_ERROR,
|
||||
MM_MOBILE_ERROR_GPRS_ROAMING_NOT_ALLOWED,
|
||||
@@ -3761,6 +3807,168 @@ simple_get_status (MMModemSimple *simple,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if LOCATION_API
|
||||
static gboolean
|
||||
gsm_lac_ci_available (MMGenericGsm *self, guint32 *out_idx)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
MMModemGsmNetworkRegStatus status;
|
||||
guint idx;
|
||||
|
||||
/* Must be registered, and have operator code, LAC and CI before GSM_LAC_CI is valid */
|
||||
status = gsm_reg_status (self, &idx);
|
||||
if (out_idx)
|
||||
*out_idx = idx;
|
||||
|
||||
if ( status != MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
||||
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)
|
||||
return FALSE;
|
||||
|
||||
if (!priv->oper_code || !strlen (priv->oper_code))
|
||||
return FALSE;
|
||||
|
||||
if (!priv->lac[idx] || !priv->cell_id[idx])
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
update_lac_ci (MMGenericGsm *self, gulong lac, gulong ci, guint idx)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
gboolean changed = FALSE;
|
||||
|
||||
if (lac != priv->lac[idx]) {
|
||||
priv->lac[idx] = lac;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (ci != priv->cell_id[idx]) {
|
||||
priv->cell_id[idx] = ci;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
#if LOCATION_API
|
||||
if (changed && gsm_lac_ci_available (self, NULL) && priv->loc_enabled && priv->loc_signal)
|
||||
g_object_notify (G_OBJECT (self), MM_MODEM_LOCATION_LOCATION);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if LOCATION_API
|
||||
|
||||
static void
|
||||
destroy_gvalue (gpointer data)
|
||||
{
|
||||
GValue *value = (GValue *) data;
|
||||
|
||||
g_value_unset (value);
|
||||
g_slice_free (GValue, value);
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
make_location_hash (MMGenericGsm *self, GError **error)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
GHashTable *locations = NULL;
|
||||
guint32 reg_idx = 0;
|
||||
GValue *val;
|
||||
char mcc[4] = { 0, 0, 0, 0 };
|
||||
char mnc[4] = { 0, 0, 0, 0 };
|
||||
|
||||
if (priv->loc_caps == MM_MODEM_LOCATION_CAPABILITY_UNKNOWN) {
|
||||
g_set_error_literal (error,
|
||||
MM_MODEM_ERROR,
|
||||
MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
|
||||
"Modem has no location capabilities");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
locations = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
NULL, destroy_gvalue);
|
||||
|
||||
if (!gsm_lac_ci_available (self, ®_idx))
|
||||
return locations;
|
||||
|
||||
memcpy (mcc, priv->oper_code, 3);
|
||||
/* Not all modems report 6-digit MNCs */
|
||||
memcpy (mnc, priv->oper_code + 3, 2);
|
||||
if (strlen (priv->oper_code) == 6)
|
||||
mnc[2] = priv->oper_code[5];
|
||||
|
||||
val = g_slice_new0 (GValue);
|
||||
g_value_init (val, G_TYPE_STRING);
|
||||
g_value_take_string (val, g_strdup_printf ("%s,%s,%lX,%lX",
|
||||
mcc,
|
||||
mnc,
|
||||
priv->lac[reg_idx],
|
||||
priv->cell_id[reg_idx]));
|
||||
g_hash_table_insert (locations,
|
||||
GUINT_TO_POINTER (MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI),
|
||||
val);
|
||||
|
||||
return locations;
|
||||
}
|
||||
|
||||
static void
|
||||
location_enable (MMModemLocation *modem,
|
||||
gboolean loc_enable,
|
||||
gboolean signal_location,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMGenericGsm *self = MM_GENERIC_GSM (modem);
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
MMCallbackInfo *info;
|
||||
|
||||
if (loc_enable != priv->loc_enabled) {
|
||||
priv->loc_enabled = loc_enable;
|
||||
g_object_notify (G_OBJECT (modem), MM_MODEM_LOCATION_ENABLED);
|
||||
}
|
||||
|
||||
if (signal_location != priv->loc_signal) {
|
||||
priv->loc_signal = signal_location;
|
||||
g_object_notify (G_OBJECT (modem), MM_MODEM_LOCATION_SIGNALS_LOCATION);
|
||||
}
|
||||
|
||||
if (loc_enable && signal_location && gsm_lac_ci_available (self, NULL))
|
||||
g_object_notify (G_OBJECT (modem), MM_MODEM_LOCATION_LOCATION);
|
||||
|
||||
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
location_get (MMModemLocation *modem,
|
||||
MMModemLocationGetFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMGenericGsm *self = MM_GENERIC_GSM (modem);
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||
GHashTable *locations = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
if (priv->loc_caps == MM_MODEM_LOCATION_CAPABILITY_UNKNOWN) {
|
||||
error = g_error_new_literal (MM_MODEM_ERROR,
|
||||
MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
|
||||
"Modem has no location capabilities");
|
||||
} else if (priv->loc_enabled)
|
||||
locations = make_location_hash (self, &error);
|
||||
else
|
||||
locations = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
callback (modem, locations, error, user_data);
|
||||
if (locations)
|
||||
g_hash_table_destroy (locations);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
#endif /* LOCATION_API */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
modem_state_changed (MMGenericGsm *self, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
@@ -3797,6 +4005,15 @@ modem_init (MMModem *modem_class)
|
||||
modem_class->set_charset = set_charset;
|
||||
}
|
||||
|
||||
#if LOCATION_API
|
||||
static void
|
||||
modem_location_init (MMModemLocation *class)
|
||||
{
|
||||
class->enable = location_enable;
|
||||
class->get_location = location_get;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
modem_gsm_card_init (MMModemGsmCard *class)
|
||||
{
|
||||
@@ -3851,6 +4068,24 @@ mm_generic_gsm_init (MMGenericGsm *self)
|
||||
MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY,
|
||||
MM_MODEM_GSM_NETWORK_DBUS_INTERFACE);
|
||||
|
||||
#if LOCATION_API
|
||||
mm_properties_changed_signal_register_property (G_OBJECT (self),
|
||||
MM_MODEM_LOCATION_CAPABILITIES,
|
||||
MM_MODEM_LOCATION_DBUS_INTERFACE);
|
||||
|
||||
mm_properties_changed_signal_register_property (G_OBJECT (self),
|
||||
MM_MODEM_LOCATION_ENABLED,
|
||||
MM_MODEM_LOCATION_DBUS_INTERFACE);
|
||||
|
||||
mm_properties_changed_signal_register_property (G_OBJECT (self),
|
||||
MM_MODEM_LOCATION_SIGNALS_LOCATION,
|
||||
MM_MODEM_LOCATION_DBUS_INTERFACE);
|
||||
|
||||
mm_properties_changed_signal_register_property (G_OBJECT (self),
|
||||
MM_MODEM_LOCATION_LOCATION,
|
||||
MM_MODEM_LOCATION_DBUS_INTERFACE);
|
||||
#endif
|
||||
|
||||
g_signal_connect (self, "notify::" MM_MODEM_STATE,
|
||||
G_CALLBACK (modem_state_changed), NULL);
|
||||
}
|
||||
@@ -3869,6 +4104,12 @@ set_property (GObject *object, guint prop_id,
|
||||
case MM_GENERIC_GSM_PROP_SUPPORTED_MODES:
|
||||
case MM_GENERIC_GSM_PROP_ALLOWED_MODE:
|
||||
case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY:
|
||||
#if LOCATION_API
|
||||
case MM_GENERIC_GSM_PROP_LOC_CAPABILITIES:
|
||||
case MM_GENERIC_GSM_PROP_LOC_ENABLED:
|
||||
case MM_GENERIC_GSM_PROP_LOC_SIGNAL:
|
||||
case MM_GENERIC_GSM_PROP_LOC_LOCATION:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@@ -3881,6 +4122,9 @@ get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (object);
|
||||
#if LOCATION_API
|
||||
GHashTable *locations = NULL;
|
||||
#endif
|
||||
|
||||
switch (prop_id) {
|
||||
case MM_MODEM_PROP_DATA_DEVICE:
|
||||
@@ -3926,6 +4170,27 @@ get_property (GObject *object, guint prop_id,
|
||||
else
|
||||
g_value_set_uint (value, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
|
||||
break;
|
||||
#if LOCATION_API
|
||||
case MM_GENERIC_GSM_PROP_LOC_CAPABILITIES:
|
||||
g_value_set_uint (value, priv->loc_caps);
|
||||
break;
|
||||
case MM_GENERIC_GSM_PROP_LOC_ENABLED:
|
||||
g_value_set_boolean (value, priv->loc_enabled);
|
||||
break;
|
||||
case MM_GENERIC_GSM_PROP_LOC_SIGNAL:
|
||||
g_value_set_boolean (value, priv->loc_signal);
|
||||
break;
|
||||
case MM_GENERIC_GSM_PROP_LOC_LOCATION:
|
||||
/* We don't allow property accesses unless location change signalling
|
||||
* is enabled, for security reasons.
|
||||
*/
|
||||
if (priv->loc_enabled && priv->loc_signal)
|
||||
locations = make_location_hash (MM_GENERIC_GSM (object), NULL);
|
||||
else
|
||||
locations = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
g_value_take_boxed (value, locations);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -4004,6 +4269,24 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass)
|
||||
MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY,
|
||||
MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY);
|
||||
|
||||
#if LOCATION_API
|
||||
g_object_class_override_property (object_class,
|
||||
MM_GENERIC_GSM_PROP_LOC_CAPABILITIES,
|
||||
MM_MODEM_LOCATION_CAPABILITIES);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
MM_GENERIC_GSM_PROP_LOC_ENABLED,
|
||||
MM_MODEM_LOCATION_ENABLED);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
MM_GENERIC_GSM_PROP_LOC_SIGNAL,
|
||||
MM_MODEM_LOCATION_SIGNALS_LOCATION);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
MM_GENERIC_GSM_PROP_LOC_LOCATION,
|
||||
MM_MODEM_LOCATION_LOCATION);
|
||||
#endif
|
||||
|
||||
g_object_class_install_property
|
||||
(object_class, MM_GENERIC_GSM_PROP_POWER_UP_CMD,
|
||||
g_param_spec_string (MM_GENERIC_GSM_POWER_UP_CMD,
|
||||
|
@@ -17,6 +17,8 @@
|
||||
#ifndef MM_GENERIC_GSM_H
|
||||
#define MM_GENERIC_GSM_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "mm-modem-gsm.h"
|
||||
#include "mm-modem-gsm-network.h"
|
||||
#include "mm-modem-base.h"
|
||||
@@ -46,7 +48,13 @@ typedef enum {
|
||||
MM_GENERIC_GSM_PROP_SUPPORTED_MODES,
|
||||
MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL,
|
||||
MM_GENERIC_GSM_PROP_ALLOWED_MODE,
|
||||
MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY
|
||||
MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY,
|
||||
#if LOCATION_API
|
||||
MM_GENERIC_GSM_PROP_LOC_CAPABILITIES,
|
||||
MM_GENERIC_GSM_PROP_LOC_ENABLED,
|
||||
MM_GENERIC_GSM_PROP_LOC_SIGNAL,
|
||||
MM_GENERIC_GSM_PROP_LOC_LOCATION,
|
||||
#endif
|
||||
} MMGenericGsmProp;
|
||||
|
||||
typedef enum {
|
||||
@@ -110,6 +118,16 @@ typedef struct {
|
||||
void (*get_access_technology) (MMGenericGsm *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
/* Called by the generic class to get additional Location capabilities that
|
||||
* subclasses may implement. The MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI
|
||||
* capabilities is automatically provided by the generic class, and
|
||||
* subclasses should return a bitfield of additional location capabilities
|
||||
* they support in the callback here.
|
||||
*/
|
||||
void (*loc_get_capabilities) (MMGenericGsm *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
} MMGenericGsmClass;
|
||||
|
||||
GType mm_generic_gsm_get_type (void);
|
||||
|
@@ -257,7 +257,7 @@ mm_modem_location_init (gpointer g_iface)
|
||||
g_param_spec_boxed (MM_MODEM_LOCATION_LOCATION,
|
||||
"Location",
|
||||
"Available location information",
|
||||
G_TYPE_HASH_TABLE,
|
||||
MM_MODEM_LOCATION_PROP_TYPE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_interface_install_property
|
||||
@@ -267,7 +267,8 @@ mm_modem_location_init (gpointer g_iface)
|
||||
"Supported location information methods",
|
||||
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN,
|
||||
MM_MODEM_LOCATION_CAPABILITY_GPS_NMEA
|
||||
| MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI,
|
||||
| MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI
|
||||
| MM_MODEM_LOCATION_CAPABILITY_GPS_RAW,
|
||||
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
|
@@ -23,6 +23,10 @@
|
||||
#define MM_IS_MODEM_LOCATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_LOCATION))
|
||||
#define MM_MODEM_LOCATION_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM_LOCATION, MMModemLocation))
|
||||
|
||||
#define MM_MODEM_LOCATION_DBUS_INTERFACE "org.freedesktop.ModemManager.Modem.Location"
|
||||
|
||||
#define MM_MODEM_LOCATION_PROP_TYPE (dbus_g_type_get_map ("GHashTable", G_TYPE_UINT, G_TYPE_VALUE))
|
||||
|
||||
#define MM_MODEM_LOCATION_CAPABILITIES "location-capabilities"
|
||||
#define MM_MODEM_LOCATION_ENABLED "location-enabled"
|
||||
#define MM_MODEM_LOCATION_SIGNALS_LOCATION "signals-location"
|
||||
@@ -32,8 +36,9 @@ typedef enum {
|
||||
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN = 0x00000000,
|
||||
MM_MODEM_LOCATION_CAPABILITY_GPS_NMEA = 0x00000001,
|
||||
MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI = 0x00000002,
|
||||
MM_MODEM_LOCATION_CAPABILITY_GPS_RAW = 0x00000004,
|
||||
|
||||
MM_MODEM_LOCATION_CAPABILITY_LAST = MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI
|
||||
MM_MODEM_LOCATION_CAPABILITY_LAST = MM_MODEM_LOCATION_CAPABILITY_GPS_RAW
|
||||
} MMModemLocationCapabilities;
|
||||
|
||||
typedef struct _MMModemLocation MMModemLocation;
|
||||
|
57
test/location.py
Executable file
57
test/location.py
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/python
|
||||
# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details:
|
||||
#
|
||||
# Copyright (C) 2009 - 2010 Red Hat, Inc.
|
||||
#
|
||||
|
||||
import sys, dbus, time
|
||||
|
||||
DBUS_INTERFACE_PROPERTIES='org.freedesktop.DBus.Properties'
|
||||
MM_DBUS_SERVICE='org.freedesktop.ModemManager'
|
||||
MM_DBUS_PATH='/org/freedesktop/ModemManager'
|
||||
MM_DBUS_INTERFACE='org.freedesktop.ModemManager'
|
||||
MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
|
||||
MM_DBUS_INTERFACE_MODEM_LOCATION='org.freedesktop.ModemManager.Modem.Location'
|
||||
|
||||
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN = 0x00000000
|
||||
MM_MODEM_LOCATION_CAPABILITY_GPS_NMEA = 0x00000001
|
||||
MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI = 0x00000002
|
||||
MM_MODEM_LOCATION_CAPABILITY_GPS_RAW = 0x00000004
|
||||
|
||||
bus = dbus.SystemBus()
|
||||
proxy = bus.get_object(MM_DBUS_SERVICE, sys.argv[1])
|
||||
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
|
||||
|
||||
props = dbus.Interface(proxy, dbus_interface=DBUS_INTERFACE_PROPERTIES)
|
||||
caps = props.Get(MM_DBUS_INTERFACE_MODEM_LOCATION, "Capabilities")
|
||||
|
||||
print "Location Capabilities:"
|
||||
if caps & MM_MODEM_LOCATION_CAPABILITY_GPS_NMEA:
|
||||
print " GPS_NMEA"
|
||||
if caps & MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI:
|
||||
print " GSM_LAC_CI"
|
||||
if caps & MM_MODEM_LOCATION_CAPABILITY_GPS_RAW:
|
||||
print " GPS_RAW"
|
||||
print ""
|
||||
|
||||
loc = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_LOCATION)
|
||||
loc.Enable(True, True)
|
||||
|
||||
for i in range(0, 5):
|
||||
locations = loc.GetLocation()
|
||||
if locations.has_key(MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI):
|
||||
print "GSM_LAC_CI: %s" % str(locations[MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI])
|
||||
time.sleep(1)
|
||||
|
||||
loc.Enable(False, False)
|
||||
|
Reference in New Issue
Block a user