diff options
author | Guido Günther <agx@sigxcpu.org> | 2014-02-05 08:38:23 +0100 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2014-02-05 08:38:23 +0100 |
commit | dc645b92b9a7db3076ae34986ac219d01677d124 (patch) | |
tree | 963a5d6ad150a88a2a8ab6d994d79d539e19383a /src/mm-modem-base.c | |
parent | 87bd9deec22af69bb27226254803ac5c63b18d78 (diff) |
Imported Upstream version 0.4+git.20100624t180933.6e79d15upstream/0.4+git.20100624t180933.6e79d15
Diffstat (limited to 'src/mm-modem-base.c')
-rw-r--r-- | src/mm-modem-base.c | 431 |
1 files changed, 426 insertions, 5 deletions
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index 3d82f8e..0c39d2c 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -21,10 +21,13 @@ #include "mm-modem-base.h" #include "mm-modem.h" -#include "mm-serial-port.h" +#include "mm-at-serial-port.h" +#include "mm-qcdm-serial-port.h" #include "mm-errors.h" #include "mm-options.h" #include "mm-properties-changed-signal.h" +#include "mm-callback-info.h" +#include "mm-modem-helpers.h" static void modem_init (MMModem *modem_class); @@ -39,10 +42,19 @@ typedef struct { char *driver; char *plugin; char *device; + char *equipment_ident; + char *unlock_required; + guint32 unlock_retries; guint32 ip_method; gboolean valid; MMModemState state; + char *manf; + char *model; + char *revision; + + MMAuthProvider *authp; + GHashTable *ports; } MMModemBasePrivate; @@ -92,7 +104,7 @@ mm_modem_base_add_port (MMModemBase *self, { MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); MMPort *port = NULL; - char *key; + char *key, *device; g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); g_return_val_if_fail (subsys != NULL, NULL); @@ -111,9 +123,12 @@ mm_modem_base_add_port (MMModemBase *self, g_return_val_if_fail (port == NULL, FALSE); } - if (!strcmp (subsys, "tty")) - port = MM_PORT (mm_serial_port_new (name, ptype)); - else if (!strcmp (subsys, "net")) { + if (!strcmp (subsys, "tty")) { + if (ptype == MM_PORT_TYPE_QCDM) + port = MM_PORT (mm_qcdm_serial_port_new (name, ptype)); + else + port = MM_PORT (mm_at_serial_port_new (name, ptype)); + } else if (!strcmp (subsys, "net")) { port = MM_PORT (g_object_new (MM_TYPE_PORT, MM_PORT_DEVICE, name, MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET, @@ -124,6 +139,15 @@ mm_modem_base_add_port (MMModemBase *self, if (!port) return NULL; + if (mm_options_debug ()) { + device = mm_modem_get_device (MM_MODEM (self)); + + g_message ("(%s) type %s claimed by %s", + name, + mm_port_type_to_name (ptype), + device); + g_free (device); + } key = get_hash_key (subsys, name); g_hash_table_insert (priv->ports, key, port); return port; @@ -169,6 +193,362 @@ mm_modem_base_get_valid (MMModemBase *self) return MM_MODEM_BASE_GET_PRIVATE (self)->valid; } +const char * +mm_modem_base_get_equipment_identifier (MMModemBase *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + + return MM_MODEM_BASE_GET_PRIVATE (self)->equipment_ident; +} + +void +mm_modem_base_set_equipment_identifier (MMModemBase *self, const char *ident) +{ + MMModemBasePrivate *priv; + const char *dbus_path; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_MODEM_BASE (self)); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + + /* Only do something if the value changes */ + if ( (priv->equipment_ident == ident) + || (priv->equipment_ident && ident && !strcmp (priv->equipment_ident, ident))) + return; + + g_free (priv->equipment_ident); + priv->equipment_ident = g_strdup (ident); + + dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG); + if (dbus_path) { + if (priv->equipment_ident) + g_message ("Modem %s: Equipment identifier set (%s)", dbus_path, priv->equipment_ident); + else + g_message ("Modem %s: Equipment identifier not set", dbus_path); + } + + g_object_notify (G_OBJECT (self), MM_MODEM_EQUIPMENT_IDENTIFIER); +} + +const char * +mm_modem_base_get_unlock_required (MMModemBase *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + + return MM_MODEM_BASE_GET_PRIVATE (self)->unlock_required; +} + +void +mm_modem_base_set_unlock_required (MMModemBase *self, const char *unlock_required) +{ + MMModemBasePrivate *priv; + const char *dbus_path; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_MODEM_BASE (self)); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + + /* Only do something if the value changes */ + if ( (priv->unlock_required == unlock_required) + || ( priv->unlock_required + && unlock_required + && !strcmp (priv->unlock_required, unlock_required))) + return; + + g_free (priv->unlock_required); + priv->unlock_required = g_strdup (unlock_required); + + dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG); + if (dbus_path) { + if (priv->unlock_required) + g_message ("Modem %s: unlock required (%s)", dbus_path, priv->unlock_required); + else + g_message ("Modem %s: unlock no longer required", dbus_path); + } + + g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_REQUIRED); +} + +guint32 +mm_modem_base_get_unlock_retries (MMModemBase *self) +{ + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), 0); + + return MM_MODEM_BASE_GET_PRIVATE (self)->unlock_retries; +} + +void +mm_modem_base_set_unlock_retries (MMModemBase *self, guint unlock_retries) +{ + MMModemBasePrivate *priv; + const char *dbus_path; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_MODEM_BASE (self)); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + + /* Only do something if the value changes */ + if (priv->unlock_retries == unlock_retries) + return; + + priv->unlock_retries = unlock_retries; + + dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG); + if (dbus_path) { + g_message ("Modem %s: # unlock retries for %s is %d", + dbus_path, priv->unlock_required, priv->unlock_retries); + } + + g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_RETRIES); +} + +const char * +mm_modem_base_get_manf (MMModemBase *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + + return MM_MODEM_BASE_GET_PRIVATE (self)->manf; +} + +void +mm_modem_base_set_manf (MMModemBase *self, const char *manf) +{ + MMModemBasePrivate *priv; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_MODEM_BASE (self)); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + g_free (priv->manf); + priv->manf = g_strdup (manf); +} + +const char * +mm_modem_base_get_model (MMModemBase *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + + return MM_MODEM_BASE_GET_PRIVATE (self)->model; +} + +void +mm_modem_base_set_model (MMModemBase *self, const char *model) +{ + MMModemBasePrivate *priv; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_MODEM_BASE (self)); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + g_free (priv->model); + priv->model = g_strdup (model); +} + +const char * +mm_modem_base_get_revision (MMModemBase *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + + return MM_MODEM_BASE_GET_PRIVATE (self)->revision; +} + +void +mm_modem_base_set_revision (MMModemBase *self, const char *revision) +{ + MMModemBasePrivate *priv; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_MODEM_BASE (self)); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + g_free (priv->revision); + priv->revision = g_strdup (revision); +} + +/*************************************************************************/ +static void +card_info_simple_invoke (MMCallbackInfo *info) +{ + MMModemBase *self = MM_MODEM_BASE (info->modem); + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + MMModemInfoFn callback = (MMModemInfoFn) info->callback; + + callback (info->modem, priv->manf, priv->model, priv->revision, info->error, info->user_data); +} + +static void +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; + + manf = mm_callback_info_get_data (info, "card-info-manf"); + cmanf = mm_callback_info_get_data (info, "card-info-c-manf"); + + model = mm_callback_info_get_data (info, "card-info-model"); + cmodel = mm_callback_info_get_data (info, "card-info-c-model"); + + rev = mm_callback_info_get_data (info, "card-info-revision"); + crev = mm_callback_info_get_data (info, "card-info-c-revision"); + + /* Prefer the 'C' responses over the plain responses */ + g_free (priv->manf); + priv->manf = g_strdup (cmanf ? cmanf : manf); + g_free (priv->model); + priv->model = g_strdup (cmodel ? cmodel : model); + g_free (priv->revision); + priv->revision = g_strdup (crev ? crev : rev); + + callback (info->modem, priv->manf, priv->model, priv->revision, info->error, info->user_data); +} + +static void +info_item_done (MMCallbackInfo *info, + GString *response, + GError *error, + const char *tag, + const char *desc) +{ + const char *p; + + if (!error) { + p = mm_strip_tag (response->str, tag); + mm_callback_info_set_data (info, desc, strlen (p) ? g_strdup (p) : NULL, g_free); + } + + mm_callback_info_chain_complete_one (info); +} + +#define GET_INFO_RESP_FN(func_name, tag, desc) \ +static void \ +func_name (MMAtSerialPort *port, \ + GString *response, \ + GError *error, \ + gpointer user_data) \ +{ \ + info_item_done ((MMCallbackInfo *) user_data, response, error, tag , desc ); \ +} + +GET_INFO_RESP_FN(get_revision_done, "+GMR:", "card-info-revision") +GET_INFO_RESP_FN(get_model_done, "+GMM:", "card-info-model") +GET_INFO_RESP_FN(get_manf_done, "+GMI:", "card-info-manf") + +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") + +void +mm_modem_base_get_card_info (MMModemBase *self, + MMAtSerialPort *port, + GError *port_error, + MMModemInfoFn callback, + gpointer user_data) +{ + MMModemBasePrivate *priv; + MMCallbackInfo *info; + MMModemState state; + gboolean cached = FALSE; + GError *error = port_error; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_MODEM_BASE (self)); + g_return_if_fail (port != NULL); + g_return_if_fail (MM_IS_AT_SERIAL_PORT (port)); + g_return_if_fail (callback != NULL); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + + /* Cached info and errors schedule the callback immediately and do + * not hit up the card for it's model information. + */ + 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."); + } + } + + /* If we have cached info or an error, don't hit up the card */ + if (cached || error) { + info = mm_callback_info_new_full (MM_MODEM (self), + card_info_simple_invoke, + G_CALLBACK (callback), + user_data); + info->error = error; + mm_callback_info_schedule (info); + return; + } + + /* Otherwise, ask the card */ + info = mm_callback_info_new_full (MM_MODEM (self), + card_info_cache_invoke, + G_CALLBACK (callback), + user_data); + + mm_callback_info_chain_start (info, 6); + 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); +} + +/*****************************************************************************/ + +static gboolean +modem_auth_request (MMModem *modem, + const char *authorization, + DBusGMethodInvocation *context, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error) +{ + MMModemBase *self = MM_MODEM_BASE (modem); + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + + g_assert (priv->authp); + return !!mm_auth_provider_request_auth (priv->authp, + authorization, + G_OBJECT (self), + context, + callback, + callback_data, + notify, + error); +} + +static gboolean +modem_auth_finish (MMModem *modem, MMAuthRequest *req, GError **error) +{ + if (mm_auth_request_get_result (req) != MM_AUTH_RESULT_AUTHORIZED) { + g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_AUTHORIZATION_REQUIRED, + "This request requires the '%s' authorization", + mm_auth_request_get_authorization (req)); + return FALSE; + } + + return TRUE; +} + /*****************************************************************************/ static void @@ -176,16 +556,29 @@ mm_modem_base_init (MMModemBase *self) { MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + priv->authp = mm_auth_provider_get (); + priv->ports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); mm_properties_changed_signal_register_property (G_OBJECT (self), MM_MODEM_ENABLED, MM_MODEM_DBUS_INTERFACE); + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_EQUIPMENT_IDENTIFIER, + MM_MODEM_DBUS_INTERFACE); + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_UNLOCK_REQUIRED, + MM_MODEM_DBUS_INTERFACE); + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_UNLOCK_RETRIES, + MM_MODEM_DBUS_INTERFACE); } static void modem_init (MMModem *modem_class) { + modem_class->auth_request = modem_auth_request; + modem_class->auth_finish = modem_auth_finish; } static gboolean @@ -227,6 +620,9 @@ set_property (GObject *object, guint prop_id, case MM_MODEM_PROP_VALID: case MM_MODEM_PROP_TYPE: case MM_MODEM_PROP_ENABLED: + case MM_MODEM_PROP_EQUIPMENT_IDENTIFIER: + case MM_MODEM_PROP_UNLOCK_REQUIRED: + case MM_MODEM_PROP_UNLOCK_RETRIES: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -268,6 +664,15 @@ get_property (GObject *object, guint prop_id, case MM_MODEM_PROP_ENABLED: g_value_set_boolean (value, is_enabled (priv->state)); break; + case MM_MODEM_PROP_EQUIPMENT_IDENTIFIER: + g_value_set_string (value, priv->equipment_ident); + break; + case MM_MODEM_PROP_UNLOCK_REQUIRED: + g_value_set_string (value, priv->unlock_required); + break; + case MM_MODEM_PROP_UNLOCK_RETRIES: + g_value_set_uint (value, priv->unlock_retries); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -280,10 +685,14 @@ finalize (GObject *object) MMModemBase *self = MM_MODEM_BASE (object); MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + mm_auth_provider_cancel_for_owner (priv->authp, object); + g_hash_table_destroy (priv->ports); g_free (priv->driver); g_free (priv->plugin); g_free (priv->device); + g_free (priv->equipment_ident); + g_free (priv->unlock_required); G_OBJECT_CLASS (mm_modem_base_parent_class)->finalize (object); } @@ -336,6 +745,18 @@ mm_modem_base_class_init (MMModemBaseClass *klass) MM_MODEM_PROP_ENABLED, MM_MODEM_ENABLED); + g_object_class_override_property (object_class, + MM_MODEM_PROP_EQUIPMENT_IDENTIFIER, + MM_MODEM_EQUIPMENT_IDENTIFIER); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_UNLOCK_REQUIRED, + MM_MODEM_UNLOCK_REQUIRED); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_UNLOCK_RETRIES, + MM_MODEM_UNLOCK_RETRIES); + mm_properties_changed_signal_new (object_class); } |