aboutsummaryrefslogtreecommitdiff
path: root/src/mm-modem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-modem.c')
-rw-r--r--src/mm-modem.c219
1 files changed, 215 insertions, 4 deletions
diff --git a/src/mm-modem.c b/src/mm-modem.c
index ca2afbd7..af67864d 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -19,6 +19,7 @@
#include "mm-modem.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
+#include "mm-marshal.h"
static void impl_modem_enable (MMModem *modem, gboolean enable, DBusGMethodInvocation *context);
static void impl_modem_connect (MMModem *modem, const char *number, DBusGMethodInvocation *context);
@@ -57,27 +58,109 @@ mm_modem_enable (MMModem *self,
MMModemFn callback,
gpointer user_data)
{
+ MMModemState state;
+
g_return_if_fail (MM_IS_MODEM (self));
g_return_if_fail (callback != NULL);
+ state = mm_modem_get_state (self);
+ if (state >= MM_MODEM_STATE_ENABLED) {
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new (self, callback, user_data);
+
+ if (state == MM_MODEM_STATE_ENABLING) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
+ "The device is already being enabled.");
+ } else {
+ /* Already enabled */
+ }
+
+ mm_callback_info_schedule (info);
+ return;
+ }
+
if (MM_MODEM_GET_INTERFACE (self)->enable)
MM_MODEM_GET_INTERFACE (self)->enable (self, callback, user_data);
else
async_op_not_supported (self, callback, user_data);
}
+static void
+finish_disable (MMModem *self,
+ MMModemFn callback,
+ gpointer user_data)
+{
+
+ if (MM_MODEM_GET_INTERFACE (self)->disable)
+ MM_MODEM_GET_INTERFACE (self)->disable (self, callback, user_data);
+ else
+ async_op_not_supported (self, callback, user_data);
+}
+
+typedef struct {
+ MMModemFn callback;
+ gpointer user_data;
+} DisableDisconnectInfo;
+
+static void
+disable_disconnect_done (MMModem *self,
+ GError *error,
+ gpointer user_data)
+{
+ DisableDisconnectInfo *cb_data = user_data;
+
+ /* ignore errors */
+ if (error) {
+ g_warning ("%s: (%s): error disconnecting the modem while disabling: (%d) %s",
+ __func__,
+ mm_modem_get_device (self),
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ }
+ finish_disable (self, cb_data->callback, cb_data->user_data);
+ g_free (cb_data);
+}
+
void
mm_modem_disable (MMModem *self,
MMModemFn callback,
gpointer user_data)
{
+ MMModemState state;
+
g_return_if_fail (MM_IS_MODEM (self));
g_return_if_fail (callback != NULL);
- if (MM_MODEM_GET_INTERFACE (self)->disable)
- MM_MODEM_GET_INTERFACE (self)->disable (self, callback, user_data);
- else
- async_op_not_supported (self, callback, user_data);
+ state = mm_modem_get_state (self);
+ if (state <= MM_MODEM_STATE_DISABLING) {
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new (self, callback, user_data);
+
+ if (state == MM_MODEM_STATE_DISABLING) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
+ "The device is already being disabled.");
+ } else {
+ /* Already disabled */
+ }
+
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ /* If the modem is connected, disconnect it */
+ if (state >= MM_MODEM_STATE_CONNECTING) {
+ DisableDisconnectInfo *cb_data;
+
+ cb_data = g_malloc0 (sizeof (DisableDisconnectInfo));
+ cb_data->callback = callback;
+ cb_data->user_data = user_data;
+ mm_modem_disconnect (self, disable_disconnect_done, cb_data);
+ } else
+ finish_disable (self, callback, user_data);
}
static void
@@ -97,10 +180,30 @@ mm_modem_connect (MMModem *self,
MMModemFn callback,
gpointer user_data)
{
+ MMModemState state;
+
g_return_if_fail (MM_IS_MODEM (self));
g_return_if_fail (callback != NULL);
g_return_if_fail (number != NULL);
+ state = mm_modem_get_state (self);
+ if (state >= MM_MODEM_STATE_CONNECTING) {
+ MMCallbackInfo *info;
+
+ /* Already connecting */
+ info = mm_callback_info_new (self, callback, user_data);
+ if (state == MM_MODEM_STATE_CONNECTING) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
+ "The device is already being connected.");
+ } else {
+ /* already connected */
+ }
+
+ mm_callback_info_schedule (info);
+ return;
+ }
+
if (MM_MODEM_GET_INTERFACE (self)->connect)
MM_MODEM_GET_INTERFACE (self)->connect (self, number, callback, user_data);
else
@@ -211,9 +314,30 @@ mm_modem_disconnect (MMModem *self,
MMModemFn callback,
gpointer user_data)
{
+ MMModemState state;
+
g_return_if_fail (MM_IS_MODEM (self));
g_return_if_fail (callback != NULL);
+ state = mm_modem_get_state (self);
+ if (state <= MM_MODEM_STATE_DISCONNECTING) {
+ MMCallbackInfo *info;
+
+ /* Already connecting */
+ info = mm_callback_info_new (self, callback, user_data);
+ if (state == MM_MODEM_STATE_DISCONNECTING) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
+ "The device is already being disconnected.");
+ } else {
+ /* already disconnected */
+ }
+
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+
if (MM_MODEM_GET_INTERFACE (self)->disconnect)
MM_MODEM_GET_INTERFACE (self)->disconnect (self, callback, user_data);
else
@@ -381,11 +505,78 @@ mm_modem_get_device (MMModem *self)
return device;
}
+MMModemState
+mm_modem_get_state (MMModem *self)
+{
+ MMModemState state = MM_MODEM_STATE_UNKNOWN;
+
+ g_object_get (G_OBJECT (self), MM_MODEM_STATE, &state, NULL);
+ return state;
+}
+
+static const char *
+state_to_string (MMModemState state)
+{
+ switch (state) {
+ case MM_MODEM_STATE_UNKNOWN:
+ return "unknown";
+ case MM_MODEM_STATE_DISABLED:
+ return "disabled";
+ case MM_MODEM_STATE_DISABLING:
+ return "disabling";
+ case MM_MODEM_STATE_ENABLING:
+ return "enabling";
+ case MM_MODEM_STATE_ENABLED:
+ return "enabled";
+ case MM_MODEM_STATE_SEARCHING:
+ return "searching";
+ case MM_MODEM_STATE_REGISTERED:
+ return "registered";
+ case MM_MODEM_STATE_DISCONNECTING:
+ return "disconnecting";
+ case MM_MODEM_STATE_CONNECTING:
+ return "connecting";
+ case MM_MODEM_STATE_CONNECTED:
+ return "connected";
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ g_assert_not_reached ();
+ return "(invalid)";
+}
+
+void
+mm_modem_set_state (MMModem *self,
+ MMModemState new_state,
+ MMModemStateReason reason)
+{
+ MMModemState old_state = MM_MODEM_STATE_UNKNOWN;
+ const char *dbus_path;
+
+ g_object_get (G_OBJECT (self), MM_MODEM_STATE, &old_state, NULL);
+
+ if (new_state != old_state) {
+ g_object_set (G_OBJECT (self), MM_MODEM_STATE, new_state, NULL);
+ g_signal_emit_by_name (G_OBJECT (self), "state-changed", new_state, old_state, reason);
+
+ dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
+ if (dbus_path) {
+ g_message ("Modem %s: state changed (%s -> %s)",
+ dbus_path,
+ state_to_string (old_state),
+ state_to_string (new_state));
+ }
+ }
+}
+
/*****************************************************************************/
static void
mm_modem_init (gpointer g_iface)
{
+ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
static gboolean initialized = FALSE;
if (initialized)
@@ -450,6 +641,26 @@ mm_modem_init (gpointer g_iface)
FALSE,
G_PARAM_READABLE));
+ g_object_interface_install_property
+ (g_iface,
+ g_param_spec_uint (MM_MODEM_STATE,
+ "State",
+ "State",
+ MM_MODEM_STATE_UNKNOWN,
+ MM_MODEM_STATE_LAST,
+ MM_MODEM_STATE_UNKNOWN,
+ G_PARAM_READWRITE));
+
+ /* Signals */
+ g_signal_new ("state-changed",
+ iface_type,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (MMModem, state_changed),
+ NULL, NULL,
+ mm_marshal_VOID__UINT_UINT_UINT,
+ G_TYPE_NONE, 3,
+ G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
+
initialized = TRUE;
}