aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--introspection/mm-modem.xml12
-rw-r--r--src/mm-generic-cdma.c44
-rw-r--r--src/mm-generic-gsm.c62
-rw-r--r--src/mm-modem-base.c83
-rw-r--r--src/mm-modem-helpers.c65
-rw-r--r--src/mm-modem-helpers.h10
-rw-r--r--src/mm-modem.c8
-rw-r--r--src/mm-modem.h4
-rwxr-xr-xtest/info.py1
9 files changed, 257 insertions, 32 deletions
diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml
index 7d54dd30..9391bad5 100644
--- a/introspection/mm-modem.xml
+++ b/introspection/mm-modem.xml
@@ -98,6 +98,18 @@
</tp:docstring>
</property>
+ <property name="DeviceIdentifier" type="s" access="read">
+ <tp:docstring>
+ A best-effort device identifier based on various device information like
+ model name, firmware revision, USB/PCI/PCMCIA IDs, and other properties.
+ This ID is not guaranteed to be unique and may be shared between
+ identical devices with the same firmware, but is intended to be
+ "unique enough" for use as a casual device identifier for various
+ user experience operations. This is not the device's IMEI or ESN since
+ those may not be available before unlocking the device via a PIN.
+ </tp:docstring>
+ </property>
+
<property name="MasterDevice" type="s" access="read">
<tp:docstring>
The physical modem device reference (ie, USB, PCI, PCMCIA device), which
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c
index 3dc3de4d..4dd1f0ef 100644
--- a/src/mm-generic-cdma.c
+++ b/src/mm-generic-cdma.c
@@ -162,6 +162,47 @@ initial_esn_check (MMGenericCdma *self)
}
}
+static void
+get_info_cb (MMModem *modem,
+ const char *manufacturer,
+ const char *model,
+ const char *version,
+ GError *error,
+ gpointer user_data)
+{
+ /* Base class handles saving the info for us */
+ if (modem)
+ mm_serial_port_close (MM_SERIAL_PORT (MM_GENERIC_CDMA_GET_PRIVATE (modem)->primary));
+}
+
+static void
+initial_info_check (MMGenericCdma *self)
+{
+ GError *error = NULL;
+ MMGenericCdmaPrivate *priv;
+
+ g_return_if_fail (MM_IS_GENERIC_CDMA (self));
+ priv = MM_GENERIC_CDMA_GET_PRIVATE (self);
+
+ g_return_if_fail (priv->primary != NULL);
+
+ if (mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &error)) {
+ /* Make sure echoing is off */
+ mm_at_serial_port_queue_command (priv->primary, "E0", 3, NULL, NULL);
+ mm_modem_base_get_card_info (MM_MODEM_BASE (self),
+ priv->primary,
+ NULL,
+ get_info_cb,
+ NULL);
+ } else {
+ g_warning ("%s: failed to open serial port: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+}
+
static gboolean
owns_port (MMModem *modem, const char *subsys, const char *name)
{
@@ -215,6 +256,9 @@ mm_generic_cdma_grab_port (MMGenericCdma *self,
g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
}
+ /* Get the modem's general info */
+ initial_info_check (self);
+
/* Get modem's ESN number */
initial_esn_check (self);
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 0bdeec42..dbbd189a 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -326,6 +326,19 @@ get_imei_cb (MMModem *modem,
}
}
+static void
+get_info_cb (MMModem *modem,
+ const char *manufacturer,
+ const char *model,
+ const char *version,
+ GError *error,
+ gpointer user_data)
+{
+ /* Base class handles saving the info for us */
+ if (modem)
+ mm_serial_port_close (MM_SERIAL_PORT (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary));
+}
+
/*****************************************************************************/
static MMModemGsmNetworkRegStatus
@@ -510,6 +523,34 @@ initial_imei_check (MMGenericGsm *self)
}
}
+static void
+initial_info_check (MMGenericGsm *self)
+{
+ GError *error = NULL;
+ MMGenericGsmPrivate *priv;
+
+ g_return_if_fail (MM_IS_GENERIC_GSM (self));
+ priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+
+ g_return_if_fail (priv->primary != NULL);
+
+ if (mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &error)) {
+ /* Make sure echoing is off */
+ mm_at_serial_port_queue_command (priv->primary, "E0", 3, NULL, NULL);
+ mm_modem_base_get_card_info (MM_MODEM_BASE (self),
+ priv->primary,
+ NULL,
+ get_info_cb,
+ NULL);
+ } else {
+ g_warning ("%s: failed to open serial port: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+}
+
static gboolean
owns_port (MMModem *modem, const char *subsys, const char *name)
{
@@ -560,12 +601,15 @@ mm_generic_gsm_grab_port (MMGenericGsm *self,
g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
}
- /* Get modem's initial lock/unlock state */
- initial_pin_check (self);
+ /* Get the modem's general info */
+ initial_info_check (self);
/* Get modem's IMEI number */
initial_imei_check (self);
+ /* Get modem's initial lock/unlock state */
+ initial_pin_check (self);
+
} else if (ptype == MM_PORT_TYPE_SECONDARY)
priv->secondary = MM_AT_SERIAL_PORT (port);
} else if (MM_IS_QCDM_SERIAL_PORT (port)) {
@@ -937,17 +981,6 @@ get_allowed_mode_done (MMModem *modem,
}
}
-static void
-get_enable_info_done (MMModem *modem,
- const char *manufacturer,
- const char *model,
- const char *version,
- GError *error,
- gpointer user_data)
-{
- /* Modem base class handles the response for us */
-}
-
void
mm_generic_gsm_enable_complete (MMGenericGsm *self,
GError *error,
@@ -985,9 +1018,6 @@ 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);
- /* Grab device info right away */
- mm_modem_get_info (MM_MODEM (self), get_enable_info_done, 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);
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index 6c755479..b7bdb6ea 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -14,6 +14,7 @@
* Copyright (C) 2009 Red Hat, Inc.
*/
+#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -43,6 +44,7 @@ typedef struct {
char *plugin;
char *device;
char *equipment_ident;
+ char *device_ident;
char *unlock_required;
guint32 unlock_retries;
guint32 ip_method;
@@ -52,6 +54,9 @@ typedef struct {
char *manf;
char *model;
char *revision;
+ char *ati;
+ char *ati1;
+ char *gsn;
MMAuthProvider *authp;
@@ -396,7 +401,7 @@ card_info_cache_invoke (MMCallbackInfo *info)
MMModemBase *self = MM_MODEM_BASE (info->modem);
MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
MMModemInfoFn callback = (MMModemInfoFn) info->callback;
- const char *manf, *cmanf, *model, *cmodel, *rev, *crev;
+ const char *manf, *cmanf, *model, *cmodel, *rev, *crev, *ati, *ati1, *gsn, *cgsn;
manf = mm_callback_info_get_data (info, "card-info-manf");
cmanf = mm_callback_info_get_data (info, "card-info-c-manf");
@@ -415,6 +420,32 @@ card_info_cache_invoke (MMCallbackInfo *info)
g_free (priv->revision);
priv->revision = g_strdup (crev ? crev : rev);
+ ati = mm_callback_info_get_data (info, "card-info-ati");
+ g_free (priv->ati);
+ priv->ati = g_strdup (ati);
+
+ ati1 = mm_callback_info_get_data (info, "card-info-ati1");
+ g_free (priv->ati1);
+ priv->ati1 = g_strdup (ati1);
+
+ gsn = mm_callback_info_get_data (info, "card-info-gsn");
+ cgsn = mm_callback_info_get_data (info, "card-info-c-gsn");
+ g_free (priv->gsn);
+ priv->gsn = g_strdup (cgsn ? cgsn : gsn);
+
+ /* Build up the device identifier */
+ g_free (priv->device_ident);
+ priv->device_ident = mm_create_device_identifier (NULL,
+ NULL,
+ priv->ati,
+ priv->ati1,
+ priv->gsn,
+ priv->revision,
+ priv->model,
+ priv->manf,
+ mm_options_debug ());
+ g_object_notify (G_OBJECT (self), MM_MODEM_DEVICE_IDENTIFIER);
+
callback (info->modem, priv->manf, priv->model, priv->revision, info->error, info->user_data);
}
@@ -425,10 +456,11 @@ info_item_done (MMCallbackInfo *info,
const char *tag,
const char *desc)
{
- const char *p;
+ const char *p = response->str;
if (!error) {
- p = mm_strip_tag (response->str, tag);
+ if (tag)
+ p = mm_strip_tag (response->str, tag);
mm_callback_info_set_data (info, desc, strlen (p) ? g_strdup (p) : NULL, g_free);
}
@@ -453,6 +485,11 @@ GET_INFO_RESP_FN(get_c_revision_done, "+CGMR:", "card-info-c-revision")
GET_INFO_RESP_FN(get_c_model_done, "+CGMM:", "card-info-c-model")
GET_INFO_RESP_FN(get_c_manf_done, "+CGMI:", "card-info-c-manf")
+GET_INFO_RESP_FN(get_ati_done, NULL, "card-info-ati")
+GET_INFO_RESP_FN(get_ati1_done, NULL, "card-info-ati1")
+GET_INFO_RESP_FN(get_gsn_done, "+GSN:", "card-info-gsn")
+GET_INFO_RESP_FN(get_cgsn_done, "+CGSN:", "card-info-c-gsn")
+
void
mm_modem_base_get_card_info (MMModemBase *self,
MMAtSerialPort *port,
@@ -462,7 +499,6 @@ mm_modem_base_get_card_info (MMModemBase *self,
{
MMModemBasePrivate *priv;
MMCallbackInfo *info;
- MMModemState state;
gboolean cached = FALSE;
GError *error = port_error;
@@ -479,16 +515,8 @@ mm_modem_base_get_card_info (MMModemBase *self,
*/
if (priv->manf || priv->model || priv->revision)
cached = TRUE;
- else {
- state = mm_modem_get_state (MM_MODEM (self));
-
- if (port_error)
- error = g_error_copy (port_error);
- else if (state < MM_MODEM_STATE_ENABLING) {
- error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "The modem is not enabled.");
- }
- }
+ else if (port_error)
+ error = g_error_copy (port_error);
/* If we have cached info or an error, don't hit up the card */
if (cached || error) {
@@ -507,13 +535,19 @@ mm_modem_base_get_card_info (MMModemBase *self,
G_CALLBACK (callback),
user_data);
- mm_callback_info_chain_start (info, 6);
+ mm_callback_info_chain_start (info, 10);
+
mm_at_serial_port_queue_command_cached (port, "+GMI", 3, get_manf_done, info);
mm_at_serial_port_queue_command_cached (port, "+GMM", 3, get_model_done, info);
mm_at_serial_port_queue_command_cached (port, "+GMR", 3, get_revision_done, info);
mm_at_serial_port_queue_command_cached (port, "+CGMI", 3, get_c_manf_done, info);
mm_at_serial_port_queue_command_cached (port, "+CGMM", 3, get_c_model_done, info);
mm_at_serial_port_queue_command_cached (port, "+CGMR", 3, get_c_revision_done, info);
+
+ mm_at_serial_port_queue_command_cached (port, "I", 3, get_ati_done, info);
+ mm_at_serial_port_queue_command_cached (port, "I1", 3, get_ati1_done, info);
+ mm_at_serial_port_queue_command_cached (port, "+GSN", 3, get_gsn_done, info);
+ mm_at_serial_port_queue_command_cached (port, "+CGSN", 3, get_cgsn_done, info);
}
/*****************************************************************************/
@@ -574,6 +608,10 @@ mm_modem_base_init (MMModemBase *self)
NULL,
MM_MODEM_DBUS_INTERFACE);
mm_properties_changed_signal_register_property (G_OBJECT (self),
+ MM_MODEM_DEVICE_IDENTIFIER,
+ NULL,
+ MM_MODEM_DBUS_INTERFACE);
+ mm_properties_changed_signal_register_property (G_OBJECT (self),
MM_MODEM_UNLOCK_REQUIRED,
NULL,
MM_MODEM_DBUS_INTERFACE);
@@ -630,6 +668,7 @@ set_property (GObject *object, guint prop_id,
case MM_MODEM_PROP_TYPE:
case MM_MODEM_PROP_ENABLED:
case MM_MODEM_PROP_EQUIPMENT_IDENTIFIER:
+ case MM_MODEM_PROP_DEVICE_IDENTIFIER:
case MM_MODEM_PROP_UNLOCK_REQUIRED:
case MM_MODEM_PROP_UNLOCK_RETRIES:
break;
@@ -676,6 +715,9 @@ get_property (GObject *object, guint prop_id,
case MM_MODEM_PROP_EQUIPMENT_IDENTIFIER:
g_value_set_string (value, priv->equipment_ident);
break;
+ case MM_MODEM_PROP_DEVICE_IDENTIFIER:
+ g_value_set_string (value, priv->device_ident);
+ break;
case MM_MODEM_PROP_UNLOCK_REQUIRED:
g_value_set_string (value, priv->unlock_required);
break;
@@ -701,7 +743,14 @@ finalize (GObject *object)
g_free (priv->plugin);
g_free (priv->device);
g_free (priv->equipment_ident);
+ g_free (priv->device_ident);
g_free (priv->unlock_required);
+ g_free (priv->manf);
+ g_free (priv->model);
+ g_free (priv->revision);
+ g_free (priv->ati);
+ g_free (priv->ati1);
+ g_free (priv->gsn);
G_OBJECT_CLASS (mm_modem_base_parent_class)->finalize (object);
}
@@ -759,6 +808,10 @@ mm_modem_base_class_init (MMModemBaseClass *klass)
MM_MODEM_EQUIPMENT_IDENTIFIER);
g_object_class_override_property (object_class,
+ MM_MODEM_PROP_DEVICE_IDENTIFIER,
+ MM_MODEM_DEVICE_IDENTIFIER);
+
+ g_object_class_override_property (object_class,
MM_MODEM_PROP_UNLOCK_REQUIRED,
MM_MODEM_UNLOCK_REQUIRED);
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 6e76f461..11950da1 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -15,6 +15,7 @@
*/
#include <config.h>
+#include <ctype.h>
#include <glib.h>
#include <string.h>
#include <ctype.h>
@@ -803,3 +804,67 @@ mm_gsm_string_to_access_tech (const char *string)
return MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
}
+/*************************************************************************/
+
+char *
+mm_create_device_identifier (const char *vid,
+ const char *pid,
+ const char *ati,
+ const char *ati1,
+ const char *gsn,
+ const char *revision,
+ const char *model,
+ const char *manf,
+ gboolean debug)
+{
+ GString *devid;
+ GChecksum *sum;
+ char *p, *ret = NULL, *j = NULL, *dbg = NULL;
+
+ /* Build up the device identifier */
+ devid = g_string_sized_new (50);
+ if (ati)
+ g_string_append (devid, ati);
+ if (ati1) {
+ /* Only append "ATI1" if it's differnet than "ATI" */
+ if (!ati || (strcmp (ati, ati1) != 0))
+ g_string_append (devid, ati1);
+ }
+ if (gsn)
+ g_string_append (devid, gsn);
+ if (revision)
+ g_string_append (devid, revision);
+ if (model)
+ g_string_append (devid, model);
+ if (manf)
+ g_string_append (devid, manf);
+
+ if (!strlen (devid->str))
+ return NULL;
+
+ p = devid->str;
+ if (debug)
+ j = dbg = g_malloc0 (strlen (devid->str) + 1);
+
+ sum = g_checksum_new (G_CHECKSUM_SHA1);
+ while (*p) {
+ /* Strip spaces and linebreaks */
+ if (!isblank (*p) && !isspace (*p) && isascii (*p)) {
+ g_checksum_update (sum, (const guchar *) p, 1);
+ if (dbg)
+ *j++ = *p;
+ }
+ p++;
+ }
+ ret = g_strdup (g_checksum_get_string (sum));
+ g_checksum_free (sum);
+
+ if (dbg) {
+ g_debug ("Device ID source '%s'", dbg);
+ g_debug ("Device ID '%s'", ret);
+ g_free (dbg);
+ }
+
+ return ret;
+}
+
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index fb100bce..03f6dec2 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -59,5 +59,15 @@ gboolean mm_gsm_parse_cscs_support_response (const char *reply,
MMModemGsmAccessTech mm_gsm_string_to_access_tech (const char *string);
+char *mm_create_device_identifier (const char *vid,
+ const char *pid,
+ const char *ati,
+ const char *ati1,
+ const char *gsn,
+ const char *revision,
+ const char *model,
+ const char *manf,
+ gboolean debug);
+
#endif /* MM_MODEM_HELPERS_H */
diff --git a/src/mm-modem.c b/src/mm-modem.c
index 221c9eab..30605a28 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -870,6 +870,14 @@ mm_modem_init (gpointer g_iface)
g_object_interface_install_property
(g_iface,
+ g_param_spec_string (MM_MODEM_DEVICE_IDENTIFIER,
+ "DeviceIdentifier",
+ "A best-effort identifer of the device",
+ NULL,
+ G_PARAM_READABLE));
+
+ g_object_interface_install_property
+ (g_iface,
g_param_spec_string (MM_MODEM_UNLOCK_REQUIRED,
"UnlockRequired",
"Whether or not the modem requires an unlock "
diff --git a/src/mm-modem.h b/src/mm-modem.h
index 0915180b..bff7e359 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -59,6 +59,7 @@ typedef enum {
#define MM_MODEM_IP_METHOD "ip-method"
#define MM_MODEM_ENABLED "enabled"
#define MM_MODEM_EQUIPMENT_IDENTIFIER "equipment-identifier"
+#define MM_MODEM_DEVICE_IDENTIFIER "device-identifier"
#define MM_MODEM_UNLOCK_REQUIRED "unlock-required"
#define MM_MODEM_UNLOCK_RETRIES "unlock-retries"
#define MM_MODEM_VALID "valid" /* not exported */
@@ -87,7 +88,8 @@ typedef enum {
MM_MODEM_PROP_ENABLED,
MM_MODEM_PROP_EQUIPMENT_IDENTIFIER,
MM_MODEM_PROP_UNLOCK_REQUIRED,
- MM_MODEM_PROP_UNLOCK_RETRIES
+ MM_MODEM_PROP_UNLOCK_RETRIES,
+ MM_MODEM_PROP_DEVICE_IDENTIFIER
} MMModemProp;
typedef struct _MMModem MMModem;
diff --git a/test/info.py b/test/info.py
index ee8cc5a3..347f8fe8 100755
--- a/test/info.py
+++ b/test/info.py
@@ -232,6 +232,7 @@ elif mtype == 2:
print "Driver: '%s'" % (props.Get(MM_DBUS_INTERFACE_MODEM, 'Driver'))
print "Modem device: '%s'" % (props.Get(MM_DBUS_INTERFACE_MODEM, 'MasterDevice'))
print "Data device: '%s'" % (props.Get(MM_DBUS_INTERFACE_MODEM, 'Device'))
+print "Device ID: '%s'" % (props.Get(MM_DBUS_INTERFACE_MODEM, 'DeviceIdentifier'))
print ""
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)