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.
This commit is contained in:
Dan Williams
2010-10-21 16:57:37 -05:00
parent 9fa20cd018
commit 328d2369a9
9 changed files with 257 additions and 32 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
/*****************************************************************************/
@@ -573,6 +607,10 @@ mm_modem_base_init (MMModemBase *self)
MM_MODEM_EQUIPMENT_IDENTIFIER,
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,
@@ -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);
}
@@ -758,6 +807,10 @@ mm_modem_base_class_init (MMModemBaseClass *klass)
MM_MODEM_PROP_EQUIPMENT_IDENTIFIER,
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);

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -868,6 +868,14 @@ mm_modem_init (gpointer g_iface)
NULL,
G_PARAM_READABLE));
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,

View File

@@ -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;

View File

@@ -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)