aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-10-21 16:57:37 -0500
committerDan Williams <dcbw@redhat.com>2010-10-21 16:57:37 -0500
commit328d2369a9dadfae786e4c524b5ff2fd0d1a9e17 (patch)
tree66eec3af08301dbb9ffbd8a26b1f558134fb289b
parent9fa20cd018ddbbcc95fd600ca140ac85661567bd (diff)
core: add DeviceIdentifier property
This is computed before any PIN is entered, and thus before we can usually get IMEI or MEID/ESN out of the device in many cases. It's therefore not the same as EquipmentIdentifier. This is intended to be used by UI programs for matching devices with PIN numbers for automatic unlocking. While the PIN number is actually *SIM* specific, no modems allow access to the IMSI before the PIN is entered, and thus we cannot actually match the PIN with the SIM. The device ID is the next best thing we can use and should allow auto unlocking in most cases.
-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)