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-options.h"
|
||||||
#include "mm-properties-changed-signal.h"
|
#include "mm-properties-changed-signal.h"
|
||||||
#include "mm-utils.h"
|
#include "mm-utils.h"
|
||||||
|
#if LOCATION_API
|
||||||
|
#include "mm-modem-location.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void modem_init (MMModem *modem_class);
|
static void modem_init (MMModem *modem_class);
|
||||||
static void modem_gsm_card_init (MMModemGsmCard *gsm_card_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_network_init (MMModemGsmNetwork *gsm_network_class);
|
||||||
static void modem_gsm_sms_init (MMModemGsmSms *gsm_sms_class);
|
static void modem_gsm_sms_init (MMModemGsmSms *gsm_sms_class);
|
||||||
static void modem_simple_init (MMModemSimple *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_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, modem_init)
|
||||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_CARD, modem_gsm_card_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_NETWORK, modem_gsm_network_init)
|
||||||
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_SMS, modem_gsm_sms_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))
|
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))
|
#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;
|
MMAtSerialPort *secondary;
|
||||||
MMQcdmSerialPort *qcdm;
|
MMQcdmSerialPort *qcdm;
|
||||||
MMPort *data;
|
MMPort *data;
|
||||||
|
|
||||||
|
/* Location API */
|
||||||
|
guint32 loc_caps;
|
||||||
|
gboolean loc_enabled;
|
||||||
|
gboolean loc_signal;
|
||||||
} MMGenericGsmPrivate;
|
} MMGenericGsmPrivate;
|
||||||
|
|
||||||
static void get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info);
|
static void get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info);
|
||||||
@@ -139,6 +153,8 @@ static void reg_info_updated (MMGenericGsm *self,
|
|||||||
gboolean update_name,
|
gboolean update_name,
|
||||||
const char *oper_name);
|
const char *oper_name);
|
||||||
|
|
||||||
|
static void update_lac_ci (MMGenericGsm *self, gulong lac, gulong ci, guint idx);
|
||||||
|
|
||||||
MMModem *
|
MMModem *
|
||||||
mm_generic_gsm_new (const char *device,
|
mm_generic_gsm_new (const char *device,
|
||||||
const char *driver,
|
const char *driver,
|
||||||
@@ -309,9 +325,10 @@ get_imei_cb (MMModem *modem,
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static MMModemGsmNetworkRegStatus
|
static MMModemGsmNetworkRegStatus
|
||||||
gsm_reg_status (MMGenericGsm *self)
|
gsm_reg_status (MMGenericGsm *self, guint32 *out_idx)
|
||||||
{
|
{
|
||||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||||
|
guint32 idx = 1;
|
||||||
|
|
||||||
/* Some devices (Blackberries for example) will respond to +CGREG, but
|
/* Some devices (Blackberries for example) will respond to +CGREG, but
|
||||||
* return ERROR for +CREG, probably because their firmware is just stupid.
|
* 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
|
if ( priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
||||||
|| priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)
|
|| priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
|
||||||
return priv->reg_status[0];
|
idx = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if ( priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
if ( priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
||||||
|| priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)
|
|| priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
|
||||||
return priv->reg_status[1];
|
idx = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING)
|
if (priv->reg_status[0] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING) {
|
||||||
return priv->reg_status[0];
|
idx = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING)
|
if (priv->reg_status[1] == MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING) {
|
||||||
return priv->reg_status[1];
|
idx = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->reg_status[0] != MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN)
|
if (priv->reg_status[0] != MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN) {
|
||||||
return priv->reg_status[0];
|
idx = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
return priv->reg_status[1];
|
out:
|
||||||
|
if (out_idx)
|
||||||
|
*out_idx = idx;
|
||||||
|
return priv->reg_status[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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))
|
if (stay_connected && (mm_modem_get_state (MM_MODEM (self)) >= MM_MODEM_STATE_DISCONNECTING))
|
||||||
return;
|
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_HOME:
|
||||||
case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
|
case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
|
||||||
mm_modem_set_state (MM_MODEM (self), MM_MODEM_STATE_REGISTERED, reason);
|
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));
|
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
|
static void
|
||||||
reg_poll_response (MMAtSerialPort *port,
|
reg_poll_response (MMAtSerialPort *port,
|
||||||
GString *response,
|
GString *response,
|
||||||
@@ -711,6 +755,10 @@ cgreg2_done (MMAtSerialPort *port,
|
|||||||
/* Try CGREG=1 instead */
|
/* Try CGREG=1 instead */
|
||||||
mm_at_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info);
|
mm_at_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info);
|
||||||
} else {
|
} else {
|
||||||
|
#if LOCATION_API
|
||||||
|
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Success; get initial state */
|
/* Success; get initial state */
|
||||||
mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem);
|
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);
|
g_clear_error (&info->error);
|
||||||
mm_at_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info);
|
mm_at_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info);
|
||||||
} else {
|
} else {
|
||||||
|
#if LOCATION_API
|
||||||
|
add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Success; get initial state */
|
/* Success; get initial state */
|
||||||
mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem);
|
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->pin_check_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->lac[0] = 0;
|
update_lac_ci (self, 0, 0, 0);
|
||||||
priv->lac[1] = 0;
|
update_lac_ci (self, 0, 0, 1);
|
||||||
priv->cell_id[0] = 0;
|
|
||||||
priv->cell_id[1] = 0;
|
|
||||||
_internal_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 */
|
||||||
@@ -1634,9 +1684,9 @@ reg_info_updated (MMGenericGsm *self,
|
|||||||
g_return_if_fail ( rs_type == MM_GENERIC_GSM_REG_TYPE_CS
|
g_return_if_fail ( rs_type == MM_GENERIC_GSM_REG_TYPE_CS
|
||||||
|| rs_type == MM_GENERIC_GSM_REG_TYPE_PS);
|
|| 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;
|
priv->reg_status[rs_type - 1] = status;
|
||||||
if (gsm_reg_status (self) != old_status)
|
if (gsm_reg_status (self, NULL) != old_status)
|
||||||
changed = TRUE;
|
changed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1658,7 +1708,7 @@ reg_info_updated (MMGenericGsm *self,
|
|||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (self),
|
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_code,
|
||||||
priv->oper_name);
|
priv->oper_name);
|
||||||
}
|
}
|
||||||
@@ -1948,7 +1998,7 @@ reg_state_changed (MMAtSerialPort *port,
|
|||||||
{
|
{
|
||||||
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
|
||||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||||
guint32 state = 0, idx;
|
guint32 state = 0;
|
||||||
gulong lac = 0, cell_id = 0;
|
gulong lac = 0, cell_id = 0;
|
||||||
gint act = -1;
|
gint act = -1;
|
||||||
gboolean cgreg = FALSE;
|
gboolean cgreg = FALSE;
|
||||||
@@ -1974,9 +2024,7 @@ reg_state_changed (MMAtSerialPort *port,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = cgreg ? 1 : 0;
|
update_lac_ci (self, lac, cell_id, cgreg ? 1 : 0);
|
||||||
priv->lac[idx] = lac;
|
|
||||||
priv->cell_id[idx] = cell_id;
|
|
||||||
|
|
||||||
/* Only update access technology if it appeared in the CREG/CGREG response */
|
/* Only update access technology if it appeared in the CREG/CGREG response */
|
||||||
if (act != -1)
|
if (act != -1)
|
||||||
@@ -2014,7 +2062,7 @@ handle_reg_status_response (MMGenericGsm *self,
|
|||||||
{
|
{
|
||||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||||
GMatchInfo *match_info;
|
GMatchInfo *match_info;
|
||||||
guint32 status = 0, idx;
|
guint32 status = 0;
|
||||||
gulong lac = 0, ci = 0;
|
gulong lac = 0, ci = 0;
|
||||||
gint act = -1;
|
gint act = -1;
|
||||||
gboolean cgreg = FALSE;
|
gboolean cgreg = FALSE;
|
||||||
@@ -2043,9 +2091,7 @@ handle_reg_status_response (MMGenericGsm *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Success; update cached location information */
|
/* Success; update cached location information */
|
||||||
idx = cgreg ? 1 : 0;
|
update_lac_ci (self, lac, ci, cgreg ? 1 : 0);
|
||||||
priv->lac[idx] = lac;
|
|
||||||
priv->cell_id[idx] = ci;
|
|
||||||
|
|
||||||
/* Only update access technology if it appeared in the CREG/CGREG response */
|
/* Only update access technology if it appeared in the CREG/CGREG response */
|
||||||
if (act != -1)
|
if (act != -1)
|
||||||
@@ -2108,7 +2154,7 @@ get_reg_status_done (MMAtSerialPort *port,
|
|||||||
goto reg_done;
|
goto reg_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = gsm_reg_status (self);
|
status = gsm_reg_status (self, NULL);
|
||||||
if ( status != MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
if ( status != MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
|
||||||
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING
|
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING
|
||||||
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED) {
|
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED) {
|
||||||
@@ -2222,7 +2268,7 @@ do_register (MMModemGsmNetwork *modem,
|
|||||||
if (network_id) {
|
if (network_id) {
|
||||||
command = g_strdup_printf ("+COPS=1,2,\"%s\"", network_id);
|
command = g_strdup_printf ("+COPS=1,2,\"%s\"", network_id);
|
||||||
priv->manual_reg = TRUE;
|
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,,");
|
command = g_strdup ("+COPS=0,,");
|
||||||
priv->manual_reg = FALSE;
|
priv->manual_reg = FALSE;
|
||||||
}
|
}
|
||||||
@@ -2260,7 +2306,7 @@ gsm_network_reg_info_invoke (MMCallbackInfo *info)
|
|||||||
MMModemGsmNetworkRegInfoFn callback = (MMModemGsmNetworkRegInfoFn) info->callback;
|
MMModemGsmNetworkRegInfoFn callback = (MMModemGsmNetworkRegInfoFn) info->callback;
|
||||||
|
|
||||||
callback (MM_MODEM_GSM_NETWORK (info->modem),
|
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_code,
|
||||||
priv->oper_name,
|
priv->oper_name,
|
||||||
info->error,
|
info->error,
|
||||||
@@ -3564,7 +3610,7 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data)
|
|||||||
priv->roam_allowed = !home_only;
|
priv->roam_allowed = !home_only;
|
||||||
|
|
||||||
/* Don't connect if we're not supposed to be roaming */
|
/* 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)) {
|
if (home_only && (status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING)) {
|
||||||
info->error = g_error_new_literal (MM_MOBILE_ERROR,
|
info->error = g_error_new_literal (MM_MOBILE_ERROR,
|
||||||
MM_MOBILE_ERROR_GPRS_ROAMING_NOT_ALLOWED,
|
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
|
static void
|
||||||
modem_state_changed (MMGenericGsm *self, GParamSpec *pspec, gpointer user_data)
|
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;
|
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
|
static void
|
||||||
modem_gsm_card_init (MMModemGsmCard *class)
|
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_ACCESS_TECHNOLOGY,
|
||||||
MM_MODEM_GSM_NETWORK_DBUS_INTERFACE);
|
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_signal_connect (self, "notify::" MM_MODEM_STATE,
|
||||||
G_CALLBACK (modem_state_changed), NULL);
|
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_SUPPORTED_MODES:
|
||||||
case MM_GENERIC_GSM_PROP_ALLOWED_MODE:
|
case MM_GENERIC_GSM_PROP_ALLOWED_MODE:
|
||||||
case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
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)
|
GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (object);
|
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (object);
|
||||||
|
#if LOCATION_API
|
||||||
|
GHashTable *locations = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case MM_MODEM_PROP_DATA_DEVICE:
|
case MM_MODEM_PROP_DATA_DEVICE:
|
||||||
@@ -3926,6 +4170,27 @@ get_property (GObject *object, guint prop_id,
|
|||||||
else
|
else
|
||||||
g_value_set_uint (value, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
|
g_value_set_uint (value, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -4004,6 +4269,24 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass)
|
|||||||
MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY,
|
MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY,
|
||||||
MM_MODEM_GSM_NETWORK_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
|
g_object_class_install_property
|
||||||
(object_class, MM_GENERIC_GSM_PROP_POWER_UP_CMD,
|
(object_class, MM_GENERIC_GSM_PROP_POWER_UP_CMD,
|
||||||
g_param_spec_string (MM_GENERIC_GSM_POWER_UP_CMD,
|
g_param_spec_string (MM_GENERIC_GSM_POWER_UP_CMD,
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
#ifndef MM_GENERIC_GSM_H
|
#ifndef MM_GENERIC_GSM_H
|
||||||
#define MM_GENERIC_GSM_H
|
#define MM_GENERIC_GSM_H
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
#include "mm-modem-gsm.h"
|
#include "mm-modem-gsm.h"
|
||||||
#include "mm-modem-gsm-network.h"
|
#include "mm-modem-gsm-network.h"
|
||||||
#include "mm-modem-base.h"
|
#include "mm-modem-base.h"
|
||||||
@@ -46,7 +48,13 @@ typedef enum {
|
|||||||
MM_GENERIC_GSM_PROP_SUPPORTED_MODES,
|
MM_GENERIC_GSM_PROP_SUPPORTED_MODES,
|
||||||
MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL,
|
MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL,
|
||||||
MM_GENERIC_GSM_PROP_ALLOWED_MODE,
|
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;
|
} MMGenericGsmProp;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -110,6 +118,16 @@ typedef struct {
|
|||||||
void (*get_access_technology) (MMGenericGsm *self,
|
void (*get_access_technology) (MMGenericGsm *self,
|
||||||
MMModemUIntFn callback,
|
MMModemUIntFn callback,
|
||||||
gpointer user_data);
|
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;
|
} MMGenericGsmClass;
|
||||||
|
|
||||||
GType mm_generic_gsm_get_type (void);
|
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,
|
g_param_spec_boxed (MM_MODEM_LOCATION_LOCATION,
|
||||||
"Location",
|
"Location",
|
||||||
"Available location information",
|
"Available location information",
|
||||||
G_TYPE_HASH_TABLE,
|
MM_MODEM_LOCATION_PROP_TYPE,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||||
|
|
||||||
g_object_interface_install_property
|
g_object_interface_install_property
|
||||||
@@ -267,7 +267,8 @@ mm_modem_location_init (gpointer g_iface)
|
|||||||
"Supported location information methods",
|
"Supported location information methods",
|
||||||
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN,
|
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN,
|
||||||
MM_MODEM_LOCATION_CAPABILITY_GPS_NMEA
|
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,
|
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
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_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_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_CAPABILITIES "location-capabilities"
|
||||||
#define MM_MODEM_LOCATION_ENABLED "location-enabled"
|
#define MM_MODEM_LOCATION_ENABLED "location-enabled"
|
||||||
#define MM_MODEM_LOCATION_SIGNALS_LOCATION "signals-location"
|
#define MM_MODEM_LOCATION_SIGNALS_LOCATION "signals-location"
|
||||||
@@ -32,8 +36,9 @@ typedef enum {
|
|||||||
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN = 0x00000000,
|
MM_MODEM_LOCATION_CAPABILITY_UNKNOWN = 0x00000000,
|
||||||
MM_MODEM_LOCATION_CAPABILITY_GPS_NMEA = 0x00000001,
|
MM_MODEM_LOCATION_CAPABILITY_GPS_NMEA = 0x00000001,
|
||||||
MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI = 0x00000002,
|
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;
|
} MMModemLocationCapabilities;
|
||||||
|
|
||||||
typedef struct _MMModemLocation MMModemLocation;
|
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