aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/mm-generic-gsm.c260
-rw-r--r--src/mm-modem-simple.c142
-rw-r--r--src/mm-modem-simple.h46
4 files changed, 454 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b8fe2894..4ba3b750 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,8 @@ modem_manager_SOURCES = \
mm-modem-gsm-card.h \
mm-modem-gsm-network.c \
mm-modem-gsm-network.h \
+ mm-modem-simple.c \
+ mm-modem-simple.h \
mm-options.c \
mm-options.h \
mm-plugin.c \
@@ -46,6 +48,9 @@ mm-manager-glue.h: $(top_srcdir)/introspection/mm-manager.xml
mm-modem-glue.h: $(top_srcdir)/introspection/mm-modem.xml
dbus-binding-tool --prefix=mm_modem --mode=glib-server --output=$@ $<
+mm-modem-simple-glue.h: $(top_srcdir)/introspection/mm-modem-simple.xml
+ dbus-binding-tool --prefix=mm_modem_simple --mode=glib-server --output=$@ $<
+
mm-modem-cdma-glue.h: $(top_srcdir)/introspection/mm-modem-cdma.xml
dbus-binding-tool --prefix=mm_modem_cdma --mode=glib-server --output=$@ $<
@@ -59,6 +64,7 @@ mm-modem-gsm-network-glue.h: $(top_srcdir)/introspection/mm-modem-gsm-network.xm
BUILT_SOURCES = \
mm-manager-glue.h \
mm-modem-glue.h \
+ mm-modem-simple-glue.h \
mm-modem-cdma-glue.h \
mm-modem-gsm-card-glue.h \
mm-modem-gsm-network-glue.h
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index f8cf6c2b..396d2492 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -6,6 +6,7 @@
#include "mm-generic-gsm.h"
#include "mm-modem-gsm-card.h"
#include "mm-modem-gsm-network.h"
+#include "mm-modem-simple.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
#include "mm-serial-parsers.h"
@@ -1079,6 +1080,253 @@ get_signal_quality (MMModemGsmNetwork *modem,
}
/*****************************************************************************/
+/* MMModemSimple interface */
+
+typedef enum {
+ SIMPLE_STATE_BEGIN = 0,
+ SIMPLE_STATE_ENABLE,
+ SIMPLE_STATE_CHECK_PIN,
+ SIMPLE_STATE_REGISTER,
+ SIMPLE_STATE_SET_APN,
+ SIMPLE_STATE_CONNECT,
+ SIMPLE_STATE_DONE
+} SimpleState;
+
+static const char *
+simple_get_string_property (MMCallbackInfo *info, const char *name, GError **error)
+{
+ GHashTable *properties = (GHashTable *) mm_callback_info_get_data (info, "simple-connect-properties");
+ GValue *value;
+
+ value = (GValue *) g_hash_table_lookup (properties, name);
+ if (!value)
+ return NULL;
+
+ if (G_VALUE_HOLDS_STRING (value))
+ return g_value_get_string (value);
+
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Invalid property type for '%s': %s (string expected)",
+ name, G_VALUE_TYPE_NAME (value));
+
+ return NULL;
+}
+
+static void
+simple_state_machine (MMModem *modem, GError *error, gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ const char *str;
+ SimpleState state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "simple-connect-state"));
+ gboolean need_pin = FALSE;
+
+ if (error) {
+ if (state == SIMPLE_STATE_CHECK_PIN && g_error_matches (error, MM_MOBILE_ERROR, MM_MOBILE_ERROR_SIM_PIN))
+ need_pin = TRUE;
+ else {
+ info->error = g_error_copy (error);
+ goto out;
+ }
+ }
+
+ switch (state) {
+ case SIMPLE_STATE_BEGIN:
+ state = SIMPLE_STATE_ENABLE;
+ mm_modem_enable (modem, TRUE, simple_state_machine, info);
+ break;
+ case SIMPLE_STATE_ENABLE:
+ state = SIMPLE_STATE_CHECK_PIN;
+ mm_generic_gsm_check_pin (MM_GENERIC_GSM (modem), simple_state_machine, info);
+ break;
+ case SIMPLE_STATE_CHECK_PIN:
+ if (need_pin) {
+ str = simple_get_string_property (info, "pin", &info->error);
+ if (str)
+ mm_modem_gsm_card_send_pin (MM_MODEM_GSM_CARD (modem), str, simple_state_machine, info);
+ else
+ info->error = g_error_copy (error);
+ } else {
+ str = simple_get_string_property (info, "network_id", &info->error);
+ state = SIMPLE_STATE_REGISTER;
+ if (!info->error)
+ mm_modem_gsm_network_register (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info);
+ }
+ break;
+ case SIMPLE_STATE_REGISTER:
+ str = simple_get_string_property (info, "apn", &info->error);
+ if (str) {
+ state = SIMPLE_STATE_SET_APN;
+ mm_modem_gsm_network_set_apn (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info);
+ break;
+ }
+ /* Fall through */
+ case SIMPLE_STATE_SET_APN:
+ str = simple_get_string_property (info, "number", &info->error);
+ state = SIMPLE_STATE_CONNECT;
+ mm_modem_connect (modem, str, simple_state_machine, info);
+ break;
+ case SIMPLE_STATE_CONNECT:
+ state = SIMPLE_STATE_DONE;
+ break;
+ case SIMPLE_STATE_DONE:
+ break;
+ }
+
+ out:
+ if (info->error || state == SIMPLE_STATE_DONE)
+ mm_callback_info_schedule (info);
+ else
+ mm_callback_info_set_data (info, "simple-connect-state", GUINT_TO_POINTER (state), NULL);
+}
+
+static void
+simple_connect (MMModemSimple *simple,
+ GHashTable *properties,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new (MM_MODEM (simple), callback, user_data);
+ mm_callback_info_set_data (info, "simple-connect-properties",
+ g_hash_table_ref (properties),
+ (GDestroyNotify) g_hash_table_unref);
+
+ /* At least number must be present */
+ if (!simple_get_string_property (info, "number", &info->error)) {
+ if (!info->error)
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Missing number property");
+ }
+
+ simple_state_machine (MM_MODEM (simple), NULL, info);
+}
+
+
+
+static void
+simple_free_gvalue (gpointer data)
+{
+ g_value_unset ((GValue *) data);
+ g_slice_free (GValue, data);
+}
+
+static GValue *
+simple_uint_value (guint32 i)
+{
+ GValue *val;
+
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_UINT);
+ g_value_set_uint (val, i);
+
+ return val;
+}
+
+static GValue *
+simple_string_value (const char *str)
+{
+ GValue *val;
+
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_set_string (val, str);
+
+ return val;
+}
+
+static void
+simple_status_got_signal_quality (MMModem *modem,
+ guint32 result,
+ GError *error,
+ gpointer user_data)
+{
+ if (error)
+ g_warning ("Error getting signal quality: %s", error->message);
+ else
+ g_hash_table_insert ((GHashTable *) user_data, "signal_quality", simple_uint_value (result));
+}
+
+static void
+simple_status_got_band (MMModem *modem,
+ guint32 result,
+ GError *error,
+ gpointer user_data)
+{
+ /* Ignore band errors since there's no generic implementation for it */
+ if (!error)
+ g_hash_table_insert ((GHashTable *) user_data, "band", simple_uint_value (result));
+}
+
+static void
+simple_status_got_mode (MMModem *modem,
+ guint32 result,
+ GError *error,
+ gpointer user_data)
+{
+ /* Ignore network mode errors since there's no generic implementation for it */
+ if (!error)
+ g_hash_table_insert ((GHashTable *) user_data, "network_mode", simple_uint_value (result));
+}
+
+static void
+simple_status_got_reg_info (MMModemGsmNetwork *modem,
+ MMModemGsmNetworkRegStatus status,
+ const char *oper_code,
+ const char *oper_name,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ GHashTable *properties;
+
+ if (error)
+ info->error = g_error_copy (error);
+ else {
+ properties = (GHashTable *) mm_callback_info_get_data (info, "simple-get-status");
+
+ g_hash_table_insert (properties, "registration_status", simple_uint_value (status));
+ g_hash_table_insert (properties, "operator_code", simple_string_value (oper_code));
+ g_hash_table_insert (properties, "operator_name", simple_string_value (oper_name));
+ }
+
+ mm_callback_info_schedule (info);
+}
+
+static void
+simple_get_status_invoke (MMCallbackInfo *info)
+{
+ MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback;
+
+ callback (MM_MODEM_SIMPLE (info->modem),
+ (GHashTable *) mm_callback_info_get_data (info, "simple-get-status"),
+ info->error, info->user_data);
+}
+
+static void
+simple_get_status (MMModemSimple *simple,
+ MMModemSimpleGetStatusFn callback,
+ gpointer user_data)
+{
+ MMModemGsmNetwork *gsm;
+ GHashTable *properties;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (MM_MODEM (simple),
+ simple_get_status_invoke,
+ G_CALLBACK (callback),
+ user_data);
+
+ properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, simple_free_gvalue);
+ mm_callback_info_set_data (info, "simple-get-status", properties, (GDestroyNotify) g_hash_table_unref);
+
+ gsm = MM_MODEM_GSM_NETWORK (simple);
+ mm_modem_gsm_network_get_signal_quality (gsm, simple_status_got_signal_quality, properties);
+ mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties);
+ mm_modem_gsm_network_get_mode (gsm, simple_status_got_mode, properties);
+ mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, properties);
+}
+
+/*****************************************************************************/
static void
modem_init (MMModem *modem_class)
@@ -1111,6 +1359,13 @@ modem_gsm_network_init (MMModemGsmNetwork *class)
}
static void
+modem_simple_init (MMModemSimple *class)
+{
+ class->connect = simple_connect;
+ class->get_status = simple_get_status;
+}
+
+static void
mm_generic_gsm_init (MMGenericGsm *self)
{
mm_serial_set_response_parser (MM_SERIAL (self),
@@ -1237,11 +1492,16 @@ mm_generic_gsm_get_type (void)
(GInterfaceInitFunc) modem_gsm_network_init
};
+ static const GInterfaceInfo modem_simple_info = {
+ (GInterfaceInitFunc) modem_simple_init
+ };
+
generic_gsm_type = g_type_register_static (MM_TYPE_SERIAL, "MMGenericGsm", &generic_gsm_type_info, 0);
g_type_add_interface_static (generic_gsm_type, MM_TYPE_MODEM, &modem_iface_info);
g_type_add_interface_static (generic_gsm_type, MM_TYPE_MODEM_GSM_CARD, &modem_gsm_card_info);
g_type_add_interface_static (generic_gsm_type, MM_TYPE_MODEM_GSM_NETWORK, &modem_gsm_network_info);
+ g_type_add_interface_static (generic_gsm_type, MM_TYPE_MODEM_SIMPLE, &modem_simple_info);
}
return generic_gsm_type;
diff --git a/src/mm-modem-simple.c b/src/mm-modem-simple.c
new file mode 100644
index 00000000..62819cf7
--- /dev/null
+++ b/src/mm-modem-simple.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+#include <dbus/dbus-glib.h>
+
+#include "mm-modem-simple.h"
+#include "mm-errors.h"
+#include "mm-callback-info.h"
+
+static void impl_modem_simple_connect (MMModemSimple *self, GHashTable *properties, DBusGMethodInvocation *context);
+static void impl_modem_simple_get_status (MMModemSimple *self, DBusGMethodInvocation *context);
+
+#include "mm-modem-simple-glue.h"
+
+void
+mm_modem_simple_connect (MMModemSimple *self,
+ GHashTable *properties,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM_SIMPLE (self));
+ g_return_if_fail (properties != NULL);
+
+ if (MM_MODEM_SIMPLE_GET_INTERFACE (self)->connect)
+ MM_MODEM_SIMPLE_GET_INTERFACE (self)->connect (self, properties, callback, user_data);
+ else {
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
+ "Operation not supported");
+ mm_callback_info_schedule (info);
+ }
+}
+
+static void
+simple_get_status_invoke (MMCallbackInfo *info)
+{
+ MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback;
+
+ callback (MM_MODEM_SIMPLE (info->modem), NULL, info->error, info->user_data);
+}
+
+void
+mm_modem_simple_get_status (MMModemSimple *self,
+ MMModemSimpleGetStatusFn callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM_SIMPLE (self));
+
+ if (MM_MODEM_SIMPLE_GET_INTERFACE (self)->get_status)
+ MM_MODEM_SIMPLE_GET_INTERFACE (self)->get_status (self, callback, user_data);
+ else {
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (MM_MODEM (self),
+ simple_get_status_invoke,
+ G_CALLBACK (callback),
+ user_data);
+
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
+ "Operation not supported");
+ mm_callback_info_schedule (info);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+async_call_done (MMModem *modem, GError *error, gpointer user_data)
+{
+ DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
+
+ if (error)
+ dbus_g_method_return_error (context, error);
+ else
+ dbus_g_method_return (context);
+}
+
+static void
+impl_modem_simple_connect (MMModemSimple *self,
+ GHashTable *properties,
+ DBusGMethodInvocation *context)
+{
+ mm_modem_simple_connect (self, properties, async_call_done, context);
+}
+
+static void
+get_status_done (MMModem *modem,
+ GHashTable *properties,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
+
+ if (error)
+ dbus_g_method_return_error (context, error);
+ else
+ dbus_g_method_return (context, properties);
+}
+
+static void
+impl_modem_simple_get_status (MMModemSimple *self,
+ DBusGMethodInvocation *context)
+{
+ mm_modem_simple_get_status (self, get_status_done, context);
+}
+
+/*****************************************************************************/
+
+static void
+mm_modem_simple_init (gpointer g_iface)
+{
+}
+
+GType
+mm_modem_simple_get_type (void)
+{
+ static GType modem_type = 0;
+
+ if (!G_UNLIKELY (modem_type)) {
+ const GTypeInfo modem_info = {
+ sizeof (MMModemSimple), /* class_size */
+ mm_modem_simple_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL
+ };
+
+ modem_type = g_type_register_static (G_TYPE_INTERFACE,
+ "MMModemSimple",
+ &modem_info, 0);
+
+ g_type_interface_add_prerequisite (modem_type, G_TYPE_OBJECT);
+ dbus_g_object_type_install_info (modem_type, &dbus_glib_mm_modem_simple_object_info);
+ }
+
+ return modem_type;
+}
diff --git a/src/mm-modem-simple.h b/src/mm-modem-simple.h
new file mode 100644
index 00000000..435df223
--- /dev/null
+++ b/src/mm-modem-simple.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+#ifndef MM_MODEM_SIMPLE_H
+#define MM_MODEM_SIMPLE_H
+
+#include <glib-object.h>
+#include <mm-modem.h>
+
+#define MM_TYPE_MODEM_SIMPLE (mm_modem_simple_get_type ())
+#define MM_MODEM_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_SIMPLE, MMModemSimple))
+#define MM_IS_MODEM_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_SIMPLE))
+#define MM_MODEM_SIMPLE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM_SIMPLE, MMModemSimple))
+
+typedef struct _MMModemSimple MMModemSimple;
+
+typedef void (*MMModemSimpleGetStatusFn) (MMModemSimple *modem,
+ GHashTable *properties,
+ GError *error,
+ gpointer user_data);
+
+struct _MMModemSimple {
+ GTypeInterface g_iface;
+
+ /* Methods */
+ void (*connect) (MMModemSimple *self,
+ GHashTable *properties,
+ MMModemFn callback,
+ gpointer user_data);
+
+ void (*get_status) (MMModemSimple *self,
+ MMModemSimpleGetStatusFn callback,
+ gpointer user_data);
+};
+
+GType mm_modem_simple_get_type (void);
+
+void mm_modem_simple_connect (MMModemSimple *self,
+ GHashTable *properties,
+ MMModemFn callback,
+ gpointer user_data);
+
+void mm_modem_simple_get_status (MMModemSimple *self,
+ MMModemSimpleGetStatusFn callback,
+ gpointer user_data);
+
+#endif /* MM_MODEM_SIMPLE_H */