aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--configure.in7
-rw-r--r--introspection/mm-modem-cdma.xml26
-rw-r--r--introspection/mm-modem-gsm-card.xml13
-rw-r--r--introspection/mm-modem.xml23
-rw-r--r--marshallers/mm-marshal.list2
-rw-r--r--plugins/77-mm-ericsson-mbm.rules22
-rw-r--r--plugins/Makefile.am164
-rw-r--r--plugins/mm-modem-gobi-gsm.c170
-rw-r--r--plugins/mm-modem-gobi-gsm.h43
-rw-r--r--plugins/mm-modem-hso.c213
-rw-r--r--plugins/mm-modem-hso.h32
-rw-r--r--plugins/mm-modem-huawei.c231
-rw-r--r--plugins/mm-modem-huawei.h32
-rw-r--r--plugins/mm-modem-mbm.c343
-rw-r--r--plugins/mm-modem-mbm.h8
-rw-r--r--plugins/mm-modem-moto-c-gsm.c158
-rw-r--r--plugins/mm-modem-moto-c-gsm.h43
-rw-r--r--plugins/mm-modem-nokia.c69
-rw-r--r--plugins/mm-modem-nokia.h19
-rw-r--r--plugins/mm-modem-novatel-cdma.c73
-rw-r--r--plugins/mm-modem-novatel-cdma.h28
-rw-r--r--plugins/mm-modem-novatel-gsm.c103
-rw-r--r--plugins/mm-modem-novatel-gsm.h19
-rw-r--r--plugins/mm-modem-option.c42
-rw-r--r--plugins/mm-modem-option.h19
-rw-r--r--plugins/mm-modem-sierra.c80
-rw-r--r--plugins/mm-modem-sierra.h19
-rw-r--r--plugins/mm-modem-zte.c129
-rw-r--r--plugins/mm-modem-zte.h19
-rw-r--r--plugins/mm-plugin-generic.c179
-rw-r--r--plugins/mm-plugin-generic.h28
-rw-r--r--plugins/mm-plugin-gobi.c169
-rw-r--r--plugins/mm-plugin-gobi.h44
-rw-r--r--plugins/mm-plugin-hso.c310
-rw-r--r--plugins/mm-plugin-hso.h31
-rw-r--r--plugins/mm-plugin-huawei.c412
-rw-r--r--plugins/mm-plugin-huawei.h32
-rw-r--r--plugins/mm-plugin-mbm.c278
-rw-r--r--plugins/mm-plugin-mbm.h10
-rw-r--r--plugins/mm-plugin-moto-c.c160
-rw-r--r--plugins/mm-plugin-moto-c.h43
-rw-r--r--plugins/mm-plugin-nokia.c223
-rw-r--r--plugins/mm-plugin-nokia.h21
-rw-r--r--plugins/mm-plugin-novatel.c253
-rw-r--r--plugins/mm-plugin-novatel.h20
-rw-r--r--plugins/mm-plugin-option.c219
-rw-r--r--plugins/mm-plugin-option.h20
-rw-r--r--plugins/mm-plugin-sierra.c247
-rw-r--r--plugins/mm-plugin-sierra.h20
-rw-r--r--plugins/mm-plugin-zte.c219
-rw-r--r--plugins/mm-plugin-zte.h20
-rw-r--r--src/Makefile.am24
-rw-r--r--src/main.c125
-rw-r--r--src/mm-errors.c2
-rw-r--r--src/mm-generic-cdma.c466
-rw-r--r--src/mm-generic-cdma.h23
-rw-r--r--src/mm-generic-gsm.c580
-rw-r--r--src/mm-generic-gsm.h48
-rw-r--r--src/mm-manager.c561
-rw-r--r--src/mm-manager.h6
-rw-r--r--src/mm-modem-base.c156
-rw-r--r--src/mm-modem-base.h59
-rw-r--r--src/mm-modem-cdma.c136
-rw-r--r--src/mm-modem-cdma.h23
-rw-r--r--src/mm-modem-gsm-card.c86
-rw-r--r--src/mm-modem-gsm-card.h15
-rw-r--r--src/mm-modem.c181
-rw-r--r--src/mm-modem.h71
-rw-r--r--src/mm-plugin-base.c950
-rw-r--r--src/mm-plugin-base.h145
-rw-r--r--src/mm-plugin.c57
-rw-r--r--src/mm-plugin.h97
-rw-r--r--src/mm-port.c238
-rw-r--r--src/mm-port.h74
-rw-r--r--src/mm-serial-parsers.c8
-rw-r--r--src/mm-serial-port.c (renamed from src/mm-serial.c)387
-rw-r--r--src/mm-serial-port.h105
-rw-r--r--src/mm-serial.h89
-rwxr-xr-xtest/mm-test.py98
80 files changed, 7253 insertions, 2666 deletions
diff --git a/.gitignore b/.gitignore
index 21592d41..c6c7fdab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,5 @@ ModemManager.pc
marshallers/mm-marshal.[ch]
src/modem-manager
docs/spec.html
+callouts/mm-modem-probe
+
diff --git a/configure.in b/configure.in
index 5da50126..55884c96 100644
--- a/configure.in
+++ b/configure.in
@@ -12,7 +12,11 @@ AM_PROG_CC_C_O
AC_PROG_INSTALL
AC_PROG_LIBTOOL
-PKG_CHECK_MODULES(MM, dbus-glib-1 >= 0.75 glib-2.0 >= 2.14 gmodule-2.0 gobject-2.0 hal)
+PKG_CHECK_MODULES(MM, dbus-glib-1 >= 0.75 glib-2.0 >= 2.14 gmodule-2.0 gobject-2.0)
+
+PKG_CHECK_MODULES(GUDEV, gudev-1.0)
+AC_SUBST(GUDEV_CFLAGS)
+AC_SUBST(GUDEV_LIBS)
AC_ARG_WITH(dbus-sys-dir, AS_HELP_STRING([--with-dbus-sys-dir=DIR], [where D-BUS system.d directory is]))
@@ -67,6 +71,7 @@ esac
AC_CONFIG_FILES([
Makefile
marshallers/Makefile
+callouts/Makefile
src/Makefile
plugins/Makefile
test/Makefile
diff --git a/introspection/mm-modem-cdma.xml b/introspection/mm-modem-cdma.xml
index a87ce3c7..0c7e9e34 100644
--- a/introspection/mm-modem-cdma.xml
+++ b/introspection/mm-modem-cdma.xml
@@ -16,6 +16,32 @@
</arg>
</method>
+ <method name="GetEsn">
+ <tp:docstring>
+ Get the Electronic Serial Number of the card.
+ </tp:docstring>
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_cdma_get_esn"/>
+ <arg name="esn" type="s" direction="out">
+ <tp:docstring>
+ The ESN.
+ </tp:docstring>
+ </arg>
+ </method>
+
+ <method name="GetServingSystem">
+ <tp:docstring>
+ Get the Service System details of the current network, if registered.
+ </tp:docstring>
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_cdma_get_serving_system"/>
+ <arg name="info" type="(usu)" direction="out">
+ <tp:docstring>
+ A structure containing the Band Class (0 = unknown, 1 = 800 MHz, 2 = 1900 MHz), the Band ("A" - "F" as defined by IS707-A), and the System ID of the serving network.
+ </tp:docstring>
+ </arg>
+ </method>
+
<signal name="SignalQuality">
<tp:docstring>
The signal quality changed.
diff --git a/introspection/mm-modem-gsm-card.xml b/introspection/mm-modem-gsm-card.xml
index 91b0c00e..b7f66d6f 100644
--- a/introspection/mm-modem-gsm-card.xml
+++ b/introspection/mm-modem-gsm-card.xml
@@ -28,19 +28,6 @@
</arg>
</method>
- <method name="GetInfo">
- <tp:docstring>
- Get the card information (manufacturer, modem, version).
- </tp:docstring>
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_gsm_modem_get_info"/>
- <arg name="info" type="(sss)" direction="out">
- <tp:docstring>
- Structure containing manufacturer, model, and version (revision) of the card.
- </tp:docstring>
- </arg>
- </method>
-
<method name="SendPuk">
<tp:docstring>
Send the PUK and a new PIN to unlock the SIM card.
diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml
index ecf5ec8b..802c46b2 100644
--- a/introspection/mm-modem.xml
+++ b/introspection/mm-modem.xml
@@ -49,9 +49,30 @@
</arg>
</method>
+ <method name="GetInfo">
+ <tp:docstring>
+ Get the card information (manufacturer, modem, version).
+ </tp:docstring>
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_get_info"/>
+ <arg name="info" type="(sss)" direction="out">
+ <tp:docstring>
+ Structure containing manufacturer, model, and version (revision) of the card.
+ </tp:docstring>
+ </arg>
+ </method>
+
<property name="Device" type="s" access="read">
<tp:docstring>
- The device to use for IP configuration and traffic.
+ The modem port to use for IP configuration and traffic.
+ </tp:docstring>
+ </property>
+
+ <property name="MasterDevice" type="s" access="read">
+ <tp:docstring>
+ The physical modem device reference (ie, USB, PCI, PCMCIA device), which
+ may be dependent upon the operating system. In Linux for example, this
+ points to a sysfs path of the usb_device object.
</tp:docstring>
</property>
diff --git a/marshallers/mm-marshal.list b/marshallers/mm-marshal.list
index 0ef23b37..ad6a4a10 100644
--- a/marshallers/mm-marshal.list
+++ b/marshallers/mm-marshal.list
@@ -1 +1,3 @@
VOID:UINT,STRING,STRING
+VOID:STRING,STRING,UINT
+VOID:OBJECT,UINT
diff --git a/plugins/77-mm-ericsson-mbm.rules b/plugins/77-mm-ericsson-mbm.rules
new file mode 100644
index 00000000..c3acaac2
--- /dev/null
+++ b/plugins/77-mm-ericsson-mbm.rules
@@ -0,0 +1,22 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add|change", GOTO="mm_mbm_end"
+SUBSYSTEM!="usb", GOTO="mm_mbm_end"
+ENV{DEVTYPE}!="usb_device", GOTO="mm_mbm_end"
+
+# Sony-Ericsson F3507g
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1900", ENV{ID_MM_ERICSSON_MBM}="1"
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1902", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Sony-Ericsson MD300
+ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d0cf", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Dell 5530 HSDPA
+ATTRS{idVendor}=="413c", ATTRS{idProduct}=="8147", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Toshiba
+ATTRS{idVendor}=="0930", ATTRS{idProduct}=="130b", ENV{ID_MM_ERICSSON_MBM}="1"
+
+
+LABEL="mm_mbm_end"
+
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index ed8b2240..98450bcc 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,133 +1,225 @@
pkglib_LTLIBRARIES = \
+ libmm-plugin-generic.la \
+ libmm-plugin-moto-c.la \
+ libmm-plugin-gobi.la \
libmm-plugin-huawei.la \
libmm-plugin-hso.la \
- libmm-plugin-mbm.la \
libmm-plugin-option.la \
libmm-plugin-sierra.la \
libmm-plugin-novatel.la \
libmm-plugin-nokia.la \
- libmm-plugin-zte.la
+ libmm-plugin-zte.la \
+ libmm-plugin-mbm.la
+
+# Generic
+
+libmm_plugin_generic_la_SOURCES = \
+ mm-plugin-generic.c \
+ mm-plugin-generic.h
+
+libmm_plugin_generic_la_CPPFLAGS = \
+ $(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
+ -I$(top_srcdir)/src
+
+libmm_plugin_generic_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
+
+# Motorola C-series phones
+
+libmm_plugin_moto_c_la_SOURCES = \
+ mm-plugin-moto-c.c \
+ mm-plugin-moto-c.h \
+ mm-modem-moto-c-gsm.c \
+ mm-modem-moto-c-gsm.h
+
+libmm_plugin_moto_c_la_CPPFLAGS = \
+ $(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
+ -I$(top_srcdir)/src
+
+libmm_plugin_moto_c_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
+
+# Qualcomm Gobi
+
+libmm_plugin_gobi_la_SOURCES = \
+ mm-plugin-gobi.c \
+ mm-plugin-gobi.h \
+ mm-modem-gobi-gsm.c \
+ mm-modem-gobi-gsm.h
+
+libmm_plugin_gobi_la_CPPFLAGS = \
+ $(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
+ -I$(top_srcdir)/src
+
+libmm_plugin_gobi_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# Huawei
libmm_plugin_huawei_la_SOURCES = \
- mm-modem-huawei.c \
- mm-modem-huawei.h \
mm-plugin-huawei.c \
- mm-plugin-huawei.h
+ mm-plugin-huawei.h \
+ mm-modem-huawei.c \
+ mm-modem-huawei.h
libmm_plugin_huawei_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_huawei_la_LDFLAGS = -module -avoid-version
+libmm_plugin_huawei_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# HSO
libmm_plugin_hso_la_SOURCES = \
+ mm-plugin-hso.c \
+ mm-plugin-hso.h \
mm-modem-gsm-hso-glue.h \
mm-modem-hso.c \
- mm-modem-hso.h \
- mm-plugin-hso.c \
- mm-plugin-hso.h
+ mm-modem-hso.h
mm-modem-gsm-hso-glue.h: $(top_srcdir)/introspection/mm-modem-gsm-hso.xml
dbus-binding-tool --prefix=mm_modem_gsm_hso --mode=glib-server --output=$@ $<
libmm_plugin_hso_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_hso_la_LDFLAGS = -module -avoid-version
+libmm_plugin_hso_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# MBM
libmm_plugin_mbm_la_SOURCES = \
- mm-modem-mbm.c \
- mm-modem-mbm.h \
mm-plugin-mbm.c \
- mm-plugin-mbm.h
+ mm-plugin-mbm.h \
+ mm-modem-mbm.c \
+ mm-modem-mbm.h
libmm_plugin_mbm_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_mbm_la_LDFLAGS = -module -avoid-version
+libmm_plugin_mbm_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# Option
libmm_plugin_option_la_SOURCES = \
- mm-modem-option.c \
- mm-modem-option.h \
mm-plugin-option.c \
- mm-plugin-option.h
+ mm-plugin-option.h \
+ mm-modem-option.c \
+ mm-modem-option.h
libmm_plugin_option_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_option_la_LDFLAGS = -module -avoid-version
+libmm_plugin_option_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# Sierra
libmm_plugin_sierra_la_SOURCES = \
- mm-modem-sierra.c \
- mm-modem-sierra.h \
mm-plugin-sierra.c \
- mm-plugin-sierra.h
+ mm-plugin-sierra.h \
+ mm-modem-sierra.c \
+ mm-modem-sierra.h
libmm_plugin_sierra_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_sierra_la_LDFLAGS = -module -avoid-version
+libmm_plugin_sierra_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# Novatel
libmm_plugin_novatel_la_SOURCES = \
- mm-modem-novatel-cdma.c \
- mm-modem-novatel-cdma.h \
- mm-modem-novatel-gsm.c \
- mm-modem-novatel-gsm.h \
mm-plugin-novatel.c \
- mm-plugin-novatel.h
+ mm-plugin-novatel.h \
+ mm-modem-novatel-gsm.c \
+ mm-modem-novatel-gsm.h
libmm_plugin_novatel_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_novatel_la_LDFLAGS = -module -avoid-version
+libmm_plugin_novatel_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# Nokia
libmm_plugin_nokia_la_SOURCES = \
- mm-modem-nokia.c \
- mm-modem-nokia.h \
mm-plugin-nokia.c \
- mm-plugin-nokia.h
+ mm-plugin-nokia.h \
+ mm-modem-nokia.c \
+ mm-modem-nokia.h
libmm_plugin_nokia_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_nokia_la_LDFLAGS = -module -avoid-version
+libmm_plugin_nokia_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
# Zte
libmm_plugin_zte_la_SOURCES = \
- mm-modem-zte.c \
- mm-modem-zte.h \
mm-plugin-zte.c \
- mm-plugin-zte.h
+ mm-plugin-zte.h \
+ mm-modem-zte.c \
+ mm-modem-zte.h
libmm_plugin_zte_la_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I$(top_srcdir)/src
-libmm_plugin_zte_la_LDFLAGS = -module -avoid-version
+libmm_plugin_zte_la_LDFLAGS = \
+ $(GUDEV_LDFLAGS) \
+ -module \
+ -avoid-version
+
+udevrulesdir = $(UDEV_BASE_DIR)/rules.d
+udevrules_DATA = 77-mm-ericsson-mbm.rules
BUILT_SOURCES = \
mm-modem-gsm-hso-glue.h
CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = \
+ $(udevrules_DATA)
+
diff --git a/plugins/mm-modem-gobi-gsm.c b/plugins/mm-modem-gobi-gsm.c
new file mode 100644
index 00000000..54cc86af
--- /dev/null
+++ b/plugins/mm-modem-gobi-gsm.c
@@ -0,0 +1,170 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mm-modem-gobi-gsm.h"
+#include "mm-errors.h"
+#include "mm-callback-info.h"
+#include "mm-modem-gsm-card.h"
+
+static gpointer mm_modem_gobi_gsm_parent_class = NULL;
+
+MMModem *
+mm_modem_gobi_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin)
+{
+ g_return_val_if_fail (device != NULL, NULL);
+ g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
+
+ return MM_MODEM (g_object_new (MM_TYPE_MODEM_GOBI_GSM,
+ MM_MODEM_MASTER_DEVICE, device,
+ MM_MODEM_DRIVER, driver,
+ MM_MODEM_PLUGIN, plugin,
+ NULL));
+}
+
+/*****************************************************************************/
+
+static void
+get_string_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (error && response && !strcmp (response->str, "ERROR")) {
+ info->error = g_error_new_literal (MM_MOBILE_ERROR,
+ MM_MOBILE_ERROR_SIM_NOT_INSERTED,
+ "Unable to read IMSI");
+ } else if (error)
+ info->error = g_error_copy (error);
+ else
+ mm_callback_info_set_result (info, g_strdup (response->str), g_free);
+
+ mm_callback_info_schedule (info);
+}
+
+static void
+get_imsi (MMModemGsmCard *modem,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMSerialPort *primary;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command_cached (primary, "+CIMI", 3, get_string_done, info);
+}
+
+static void
+modem_gsm_card_init (MMModemGsmCard *class)
+{
+ class->get_imsi = get_imsi;
+}
+
+/*****************************************************************************/
+
+static void
+modem_init (MMModem *modem_class)
+{
+}
+
+static void
+mm_modem_gobi_gsm_init (MMModemGobiGsm *self)
+{
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+
+ /* These devices just don't implement AT+CFUN */
+
+ switch (prop_id) {
+ case MM_GENERIC_GSM_PROP_INIT_CMD:
+ g_value_set_string (value, "Z E0 V1 +CMEE=1");
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+}
+
+static void
+mm_modem_gobi_gsm_class_init (MMModemGobiGsmClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ mm_modem_gobi_gsm_parent_class = g_type_class_peek_parent (klass);
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+
+ g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_INIT_CMD,
+ MM_GENERIC_GSM_INIT_CMD);
+}
+
+GType
+mm_modem_gobi_gsm_get_type (void)
+{
+ static GType modem_gobi_gsm_type = 0;
+
+ if (G_UNLIKELY (modem_gobi_gsm_type == 0)) {
+ static const GTypeInfo modem_gobi_gsm_type_info = {
+ sizeof (MMModemGobiGsmClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mm_modem_gobi_gsm_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (MMModemGobiGsm),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mm_modem_gobi_gsm_init,
+ };
+
+ static const GInterfaceInfo modem_iface_info = {
+ (GInterfaceInitFunc) modem_init
+ };
+
+ static const GInterfaceInfo modem_gsm_card_info = {
+ (GInterfaceInitFunc) modem_gsm_card_init
+ };
+
+ modem_gobi_gsm_type = g_type_register_static (MM_TYPE_GENERIC_GSM, "MMModemGobiGsm",
+ &modem_gobi_gsm_type_info, 0);
+
+ g_type_add_interface_static (modem_gobi_gsm_type, MM_TYPE_MODEM, &modem_iface_info);
+ g_type_add_interface_static (modem_gobi_gsm_type, MM_TYPE_MODEM_GSM_CARD, &modem_gsm_card_info);
+ }
+
+ return modem_gobi_gsm_type;
+}
diff --git a/plugins/mm-modem-gobi-gsm.h b/plugins/mm-modem-gobi-gsm.h
new file mode 100644
index 00000000..4bd262fb
--- /dev/null
+++ b/plugins/mm-modem-gobi-gsm.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_MODEM_GOBI_GSM_H
+#define MM_MODEM_GOBI_GSM_H
+
+#include "mm-generic-gsm.h"
+
+#define MM_TYPE_MODEM_GOBI_GSM (mm_modem_gobi_gsm_get_type ())
+#define MM_MODEM_GOBI_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_GOBI_GSM, MMModemGobiGsm))
+#define MM_MODEM_GOBI_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_GOBI_GSM, MMModemGobiGsmClass))
+#define MM_IS_MODEM_GOBI_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_GOBI_GSM))
+#define MM_IS_MODEM_GOBI_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_GOBI_GSM))
+#define MM_MODEM_GOBI_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_GOBI_GSM, MMModemGobiGsmClass))
+
+typedef struct {
+ MMGenericGsm parent;
+} MMModemGobiGsm;
+
+typedef struct {
+ MMGenericGsmClass parent;
+} MMModemGobiGsmClass;
+
+GType mm_modem_gobi_gsm_get_type (void);
+
+MMModem *mm_modem_gobi_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin_name);
+
+#endif /* MM_MODEM_GOBI_GSM_H */
diff --git a/plugins/mm-modem-hso.c b/plugins/mm-modem-hso.c
index de960411..39c3e42b 100644
--- a/plugins/mm-modem-hso.c
+++ b/plugins/mm-modem-hso.c
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <stdlib.h>
#include <stdio.h>
@@ -7,9 +21,12 @@
#include <stdlib.h>
#include <arpa/inet.h>
#include <dbus/dbus-glib.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
#include "mm-modem-hso.h"
#include "mm-modem-simple.h"
-#include "mm-serial.h"
#include "mm-serial-parsers.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
@@ -34,26 +51,24 @@ typedef struct {
#define OWANDATA_TAG "_OWANDATA: "
MMModem *
-mm_modem_hso_new (const char *serial_device,
- const char *network_device,
- const char *driver)
+mm_modem_hso_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (serial_device != NULL, NULL);
- g_return_val_if_fail (network_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_HSO,
- MM_SERIAL_DEVICE, serial_device,
- MM_SERIAL_SEND_DELAY, (guint64) 10000,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_DEVICE, network_device,
+ MM_MODEM_PLUGIN, plugin,
MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_STATIC,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
NULL));
}
static void
-hso_enable_done (MMSerial *serial,
+hso_enable_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -86,11 +101,14 @@ hso_enable (MMModemHso *self,
{
MMCallbackInfo *info;
char *command;
+ MMSerialPort *primary;
info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
command = g_strdup_printf ("AT_OWANCALL=%d,%d,1", hso_get_cid (self), enabled ? 1 : 0);
- mm_serial_queue_command (MM_SERIAL (self), command, 3, hso_enable_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, command, 3, hso_enable_done, info);
g_free (command);
}
@@ -161,19 +179,20 @@ hso_disabled (MMModem *modem,
}
static void
-auth_done (MMSerial *serial,
+auth_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemHso *self = MM_MODEM_HSO (info->modem);
if (error) {
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
} else
/* success, kill any existing connections first */
- hso_enable (MM_MODEM_HSO (serial), FALSE, hso_disabled, info);
+ hso_enable (self, FALSE, hso_disabled, info);
}
void
@@ -184,24 +203,32 @@ mm_hso_modem_authenticate (MMModemHso *self,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
g_return_if_fail (MM_IS_MODEM_HSO (self));
g_return_if_fail (callback != NULL);
info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
if (username || password) {
char *command;
+ // FIXME: if QCPDPP fails, try OPDPP. AT&T Quicksilver uses a different
+ // chipset (ie, not Qualcomm) and the auth command is OPDPP instead of
+ // the Qualcomm-specific QCPDPP.
+
command = g_strdup_printf ("AT$QCPDPP=%d,1,\"%s\",\"%s\"",
hso_get_cid (self),
password ? password : "",
username ? username : "");
- mm_serial_queue_command (MM_SERIAL (self), command, 3, auth_done, info);
+ mm_serial_port_queue_command (primary, command, 3, auth_done, info);
g_free (command);
} else
- auth_done (MM_SERIAL (self), NULL, NULL, info);
+ auth_done (primary, NULL, NULL, info);
}
/*****************************************************************************/
@@ -234,7 +261,7 @@ parent_enable_done (MMModem *modem, GError *error, gpointer user_data)
}
static void
-modem_enable_done (MMSerial *serial,
+modem_enable_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -242,8 +269,8 @@ modem_enable_done (MMSerial *serial,
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMModem *parent_modem_iface;
- parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (serial));
- parent_modem_iface->enable (MM_MODEM (serial),
+ parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (info->modem));
+ parent_modem_iface->enable (info->modem,
GPOINTER_TO_INT (mm_callback_info_get_data (info, "enable")),
parent_enable_done, info);
}
@@ -255,14 +282,18 @@ enable (MMModem *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_new (modem, callback, user_data);
mm_callback_info_set_data (info, "enable", GINT_TO_POINTER (enable), NULL);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
if (do_enable)
- modem_enable_done (MM_SERIAL (modem), NULL, NULL, info);
+ modem_enable_done (primary, NULL, NULL, info);
else
- mm_serial_queue_command (MM_SERIAL (modem), "AT_OWANCALL=1,0,0", 3, modem_enable_done, info);
+ mm_serial_port_queue_command (primary, "AT_OWANCALL=1,0,0", 3, modem_enable_done, info);
}
static void
@@ -296,7 +327,7 @@ ip4_config_invoke (MMCallbackInfo *info)
}
static void
-get_ip4_config_done (MMSerial *serial,
+get_ip4_config_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -317,7 +348,7 @@ get_ip4_config_done (MMSerial *serial,
goto out;
}
- cid = hso_get_cid (MM_MODEM_HSO (serial));
+ cid = hso_get_cid (MM_MODEM_HSO (info->modem));
dns_array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 2);
items = g_strsplit (response->str + strlen (OWANDATA_TAG), ", ", 0);
@@ -359,10 +390,13 @@ get_ip4_config (MMModem *modem,
{
MMCallbackInfo *info;
char *command;
+ MMSerialPort *primary;
info = mm_callback_info_new_full (modem, ip4_config_invoke, G_CALLBACK (callback), user_data);
command = g_strdup_printf ("AT_OWANDATA=%d", hso_get_cid (MM_MODEM_HSO (modem)));
- mm_serial_queue_command (MM_SERIAL (modem), command, 3, get_ip4_config_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, command, 3, get_ip4_config_done, info);
g_free (command);
}
@@ -372,9 +406,12 @@ disconnect (MMModem *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_new (modem, callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "AT_OWANCALL=1,0,0", 3, NULL, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "AT_OWANCALL=1,0,0", 3, NULL, info);
}
/*****************************************************************************/
@@ -408,23 +445,25 @@ impl_hso_authenticate (MMModemHso *self,
}
static void
-connection_enabled (MMSerial *serial,
+connection_enabled (MMSerialPort *port,
GMatchInfo *info,
gpointer user_data)
{
+ MMModemHso *self = MM_MODEM_HSO (user_data);
+ MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (self);
char *str;
str = g_match_info_fetch (info, 2);
if (str[0] == '1')
- connect_pending_done (MM_MODEM_HSO (serial));
+ connect_pending_done (self);
else if (str[0] == '3') {
- MMCallbackInfo *cb_info = MM_MODEM_HSO_GET_PRIVATE (serial)->connect_pending_data;
+ MMCallbackInfo *cb_info = priv->connect_pending_data;
if (cb_info)
cb_info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Call setup failed");
- connect_pending_done (MM_MODEM_HSO (serial));
+ connect_pending_done (self);
} else if (str[0] == '0')
/* FIXME: disconnected. do something when we have modem status signals */
;
@@ -521,16 +560,83 @@ simple_connect (MMModemSimple *simple,
/*****************************************************************************/
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ const char *sys[] = { "tty", "net", NULL };
+ GUdevClient *client;
+ GUdevDevice *device = NULL;
+ MMPort *port = NULL;
+ const char *sysfs_path;
+
+ client = g_udev_client_new (sys);
+ if (!client) {
+ g_set_error (error, 0, 0, "Could not get udev client.");
+ return FALSE;
+ }
+
+ device = g_udev_client_query_by_subsystem_and_name (client, subsys, name);
+ if (!device) {
+ g_set_error (error, 0, 0, "Could not get udev device.");
+ goto out;
+ }
+
+ sysfs_path = g_udev_device_get_sysfs_path (device);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get udev device sysfs path.");
+ goto out;
+ }
+
+ if (!strcmp (subsys, "tty")) {
+ char *hsotype_path;
+ char *contents = NULL;
+
+ hsotype_path = g_build_filename (sysfs_path, "hsotype", NULL);
+ if (g_file_get_contents (hsotype_path, &contents, NULL, NULL)) {
+ if (g_str_has_prefix (contents, "Control"))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else
+ ptype = MM_PORT_TYPE_SECONDARY;
+ g_free (contents);
+ }
+ g_free (hsotype_path);
+ }
+
+ port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
+ if (!port)
+ goto out;
+
+ if (MM_IS_SERIAL_PORT (port)) {
+ g_object_set (G_OBJECT (port), MM_SERIAL_PORT_SEND_DELAY, (guint64) 10000, NULL);
+ if (ptype == MM_PORT_TYPE_PRIMARY) {
+ GRegex *regex;
+
+ mm_generic_gsm_set_unsolicited_registration (gsm, TRUE);
+
+ regex = g_regex_new ("_OWANCALL: (\\d), (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, connection_enabled, modem, NULL);
+ g_regex_unref (regex);
+ }
+ }
+
+out:
+ if (device)
+ g_object_unref (device);
+ g_object_unref (client);
+ return !!port;
+}
+
+/*****************************************************************************/
+
static void
mm_modem_hso_init (MMModemHso *self)
{
- GRegex *regex;
-
- mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (self), TRUE);
-
- regex = g_regex_new ("_OWANCALL: (\\d), (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, connection_enabled, NULL, NULL);
- g_regex_unref (regex);
}
static void
@@ -546,39 +652,7 @@ modem_init (MMModem *modem_class)
modem_class->connect = do_connect;
modem_class->get_ip4_config = get_ip4_config;
modem_class->disconnect = disconnect;
-}
-
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
-{
- GObject *object;
- char *modem_device;
- char *serial_device;
-
- object = G_OBJECT_CLASS (mm_modem_hso_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
-
- /* Make sure both serial device and data device are provided */
- g_object_get (object,
- MM_MODEM_DEVICE, &modem_device,
- MM_SERIAL_DEVICE, &serial_device,
- NULL);
-
- if (!modem_device || !serial_device || !strcmp (modem_device, serial_device)) {
- g_warning ("No network device provided");
- g_object_unref (object);
- object = NULL;
- }
-
- g_free (modem_device);
- g_free (serial_device);
-
- return object;
+ modem_class->grab_port = grab_port;
}
static void
@@ -599,7 +673,6 @@ mm_modem_hso_class_init (MMModemHsoClass *klass)
g_type_class_add_private (object_class, sizeof (MMModemHsoPrivate));
/* Virtual methods */
- object_class->constructor = constructor;
object_class->finalize = finalize;
}
diff --git a/plugins/mm-modem-hso.h b/plugins/mm-modem-hso.h
index 8780ee1a..e2d7623a 100644
--- a/plugins/mm-modem-hso.h
+++ b/plugins/mm-modem-hso.h
@@ -1,16 +1,30 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_MODEM_HSO_H
#define MM_MODEM_HSO_H
#include "mm-generic-gsm.h"
-#define MM_TYPE_MODEM_HSO (mm_modem_hso_get_type ())
-#define MM_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_HSO, MMModemHso))
-#define MM_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_HSO, MMModemHsoClass))
-#define MM_IS_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_HSO))
-#define MM_IS_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_HSO))
-#define MM_MODEM_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_HSO, MMModemHsoClass))
+#define MM_TYPE_MODEM_HSO (mm_modem_hso_get_type ())
+#define MM_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_HSO, MMModemHso))
+#define MM_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_HSO, MMModemHsoClass))
+#define MM_IS_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_HSO))
+#define MM_IS_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_HSO))
+#define MM_MODEM_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_HSO, MMModemHsoClass))
typedef struct {
MMGenericGsm parent;
@@ -22,9 +36,9 @@ typedef struct {
GType mm_modem_hso_get_type (void);
-MMModem *mm_modem_hso_new (const char *serial_device,
- const char *network_device,
- const char *driver);
+MMModem *mm_modem_hso_new (const char *device,
+ const char *driver,
+ const char *plugin);
void mm_hso_modem_authenticate (MMModemHso *self,
const char *username,
diff --git a/plugins/mm-modem-huawei.c b/plugins/mm-modem-huawei.c
index 2e6b5151..43ee34d1 100644
--- a/plugins/mm-modem-huawei.c
+++ b/plugins/mm-modem-huawei.c
@@ -1,12 +1,31 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
#include "mm-modem-huawei.h"
#include "mm-modem-gsm-network.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
+#include "mm-serial-port.h"
#include "mm-serial-parsers.h"
static gpointer mm_modem_huawei_parent_class = NULL;
@@ -14,8 +33,6 @@ static gpointer mm_modem_huawei_parent_class = NULL;
#define MM_MODEM_HUAWEI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiPrivate))
typedef struct {
- MMSerial *monitor_device;
-
/* Cached state */
guint signal_quality;
MMModemGsmNetworkMode mode;
@@ -23,20 +40,18 @@ typedef struct {
} MMModemHuaweiPrivate;
MMModem *
-mm_modem_huawei_new (const char *data_device,
- const char *monitor_device,
- const char *driver)
+mm_modem_huawei_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (data_device != NULL, NULL);
- g_return_val_if_fail (monitor_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_HUAWEI,
- MM_SERIAL_DEVICE, monitor_device,
- MM_MODEM_DEVICE, data_device,
- MM_SERIAL_CARRIER_DETECT, FALSE,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
@@ -80,24 +95,26 @@ parse_syscfg (MMModemHuawei *self,
}
static void
-set_network_mode_done (MMSerial *serial,
+set_network_mode_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemHuawei *self = MM_MODEM_HUAWEI (info->modem);
+ MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (self);
if (error)
info->error = g_error_copy (error);
else
/* Success, cache the value */
- MM_MODEM_HUAWEI_GET_PRIVATE (serial)->mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode"));
+ priv->mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode"));
mm_callback_info_schedule (info);
}
static void
-set_network_mode_get_done (MMSerial *serial,
+set_network_mode_get_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -111,7 +128,7 @@ set_network_mode_get_done (MMSerial *serial,
int a, b, u1, u2;
guint32 band;
- if (parse_syscfg (MM_MODEM_HUAWEI (serial), response->str, &a, &b, &band, &u1, &u2)) {
+ if (parse_syscfg (MM_MODEM_HUAWEI (info->modem), response->str, &a, &b, &band, &u1, &u2)) {
char *command;
switch (GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode"))) {
@@ -142,7 +159,7 @@ set_network_mode_get_done (MMSerial *serial,
}
command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
- mm_serial_queue_command (serial, command, 3, set_network_mode_done, info);
+ mm_serial_port_queue_command (port, command, 3, set_network_mode_done, info);
g_free (command);
}
}
@@ -155,6 +172,7 @@ set_network_mode (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
@@ -174,9 +192,10 @@ set_network_mode (MMModemGsmNetwork *modem,
case MM_MODEM_GSM_NETWORK_MODE_3G_ONLY:
/* Allowed values */
mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL);
- mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, set_network_mode_get_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_network_mode_get_done, info);
return;
- break;
default:
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid mode.");
break;
@@ -186,19 +205,21 @@ set_network_mode (MMModemGsmNetwork *modem,
}
static void
-get_network_mode_done (MMSerial *serial,
+get_network_mode_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemHuawei *self = MM_MODEM_HUAWEI (info->modem);
+ MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (self);
int mode_a, mode_b, u1, u2;
guint32 band;
if (error)
info->error = g_error_copy (error);
- else if (parse_syscfg (MM_MODEM_HUAWEI (serial), response->str, &mode_a, &mode_b, &band, &u1, &u2))
- mm_callback_info_set_result (info, GUINT_TO_POINTER (MM_MODEM_HUAWEI_GET_PRIVATE (serial)->mode), NULL);
+ else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2))
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->mode), NULL);
mm_callback_info_schedule (info);
}
@@ -220,36 +241,42 @@ get_network_mode (MMModemGsmNetwork *modem,
} else {
/* Get it from modem */
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, get_network_mode_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_network_mode_done, info);
}
}
static void
-set_band_done (MMSerial *serial,
+set_band_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemHuawei *self = MM_MODEM_HUAWEI (info->modem);
+ MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (self);
if (error)
info->error = g_error_copy (error);
else
/* Success, cache the value */
- MM_MODEM_HUAWEI_GET_PRIVATE (serial)->band = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"));
+ priv->band = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"));
mm_callback_info_schedule (info);
}
static void
-set_band_get_done (MMSerial *serial,
+set_band_get_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemHuawei *self = MM_MODEM_HUAWEI (info->modem);
if (error) {
info->error = g_error_copy (error);
@@ -258,7 +285,7 @@ set_band_get_done (MMSerial *serial,
int a, b, u1, u2;
guint32 band;
- if (parse_syscfg (MM_MODEM_HUAWEI (serial), response->str, &a, &b, &band, &u1, &u2)) {
+ if (parse_syscfg (self, response->str, &a, &b, &band, &u1, &u2)) {
char *command;
switch (GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"))) {
@@ -278,7 +305,7 @@ set_band_get_done (MMSerial *serial,
}
command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
- mm_serial_queue_command (serial, command, 3, set_band_done, info);
+ mm_serial_port_queue_command (port, command, 3, set_band_done, info);
g_free (command);
}
}
@@ -291,6 +318,7 @@ set_band (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
@@ -301,29 +329,34 @@ set_band (MMModemGsmNetwork *modem,
case MM_MODEM_GSM_NETWORK_BAND_U2100:
case MM_MODEM_GSM_NETWORK_BAND_PCS:
mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (band), NULL);
- mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, set_band_get_done, info);
- break;
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_band_get_done, info);
+ return;
default:
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid band.");
- mm_callback_info_schedule (info);
break;
}
+
+ mm_callback_info_schedule (info);
}
static void
-get_band_done (MMSerial *serial,
+get_band_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemHuawei *self = MM_MODEM_HUAWEI (info->modem);
+ MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (self);
int mode_a, mode_b, u1, u2;
guint32 band;
if (error)
info->error = g_error_copy (error);
- else if (parse_syscfg (MM_MODEM_HUAWEI (serial), response->str, &mode_a, &mode_b, &band, &u1, &u2))
- mm_callback_info_set_result (info, GUINT_TO_POINTER (MM_MODEM_HUAWEI_GET_PRIVATE (serial)->band), NULL);
+ else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2))
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->band), NULL);
mm_callback_info_schedule (info);
}
@@ -334,6 +367,7 @@ get_band (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (modem);
+ MMSerialPort *primary;
if (priv->band != MM_MODEM_GSM_NETWORK_BAND_ANY) {
/* have cached mode (from an unsolicited message). Use that */
@@ -347,7 +381,9 @@ get_band (MMModemGsmNetwork *modem,
MMCallbackInfo *info;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, get_band_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_band_done, info);
}
}
@@ -377,10 +413,12 @@ get_signal_quality (MMModemGsmNetwork *modem,
/* Unsolicited message handlers */
static void
-handle_signal_quality_change (MMSerial *serial,
+handle_signal_quality_change (MMSerialPort *port,
GMatchInfo *match_info,
gpointer user_data)
{
+ MMModemHuawei *self = MM_MODEM_HUAWEI (user_data);
+ MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (self);
char *str;
int quality;
@@ -396,16 +434,17 @@ handle_signal_quality_change (MMSerial *serial,
quality = quality * 100 / 31;
g_debug ("Signal quality: %d", quality);
- MM_MODEM_HUAWEI_GET_PRIVATE (serial)->signal_quality = (guint32) quality;
- mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (serial), (guint32) quality);
+ priv->signal_quality = (guint32) quality;
+ mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (self), (guint32) quality);
}
static void
-handle_mode_change (MMSerial *serial,
+handle_mode_change (MMSerialPort *port,
GMatchInfo *match_info,
gpointer user_data)
{
- MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (serial);
+ MMModemHuawei *self = MM_MODEM_HUAWEI (user_data);
+ MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (self);
char *str;
int a;
int b;
@@ -436,11 +475,11 @@ handle_mode_change (MMSerial *serial,
}
g_debug ("Mode: %d", priv->mode);
- mm_modem_gsm_network_mode (MM_MODEM_GSM_NETWORK (serial), priv->mode);
+ mm_modem_gsm_network_mode (MM_MODEM_GSM_NETWORK (self), priv->mode);
}
static void
-handle_status_change (MMSerial *serial,
+handle_status_change (MMSerialPort *port,
GMatchInfo *match_info,
gpointer user_data)
{
@@ -457,6 +496,92 @@ handle_status_change (MMSerial *serial,
/*****************************************************************************/
+/* user_data != NULL means the port is a secondary port */
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ const char *sys[] = { "tty", NULL };
+ GUdevClient *client;
+ GUdevDevice *device = NULL;
+ MMPort *port = NULL;
+ int usbif;
+
+ client = g_udev_client_new (sys);
+ if (!client) {
+ g_set_error (error, 0, 0, "Could not get udev client.");
+ return FALSE;
+ }
+
+ device = g_udev_client_query_by_subsystem_and_name (client, subsys, name);
+ if (!device) {
+ g_set_error (error, 0, 0, "Could not get udev device.");
+ goto out;
+ }
+
+ usbif = g_udev_device_get_property_as_int (device, "ID_USB_INTERFACE_NUM");
+ if (usbif < 0) {
+ g_set_error (error, 0, 0, "Could not get USB device interface number.");
+ goto out;
+ }
+
+ if (usbif == 0) {
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ } else if (user_data) {
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY))
+ ptype = MM_PORT_TYPE_SECONDARY;
+ }
+
+ port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
+ if (!port)
+ goto out;
+
+ if (MM_IS_SERIAL_PORT (port)) {
+ g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL);
+ if (ptype == MM_PORT_TYPE_SECONDARY) {
+ GRegex *regex;
+
+ mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (modem), TRUE);
+
+ regex = g_regex_new ("\\r\\n\\^RSSI:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_signal_quality_change, modem, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_mode_change, modem, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_status_change, modem, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, modem, NULL);
+ g_regex_unref (regex);
+ }
+ }
+
+out:
+ if (device)
+ g_object_unref (device);
+ g_object_unref (client);
+ return !!port;
+}
+
+/*****************************************************************************/
+
+static void
+modem_init (MMModem *modem_class)
+{
+ modem_class->grab_port = grab_port;
+}
+
static void
modem_gsm_network_init (MMModemGsmNetwork *class)
{
@@ -470,25 +595,6 @@ modem_gsm_network_init (MMModemGsmNetwork *class)
static void
mm_modem_huawei_init (MMModemHuawei *self)
{
- GRegex *regex;
-
- mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (self), TRUE);
-
- regex = g_regex_new ("\\r\\n\\^RSSI:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, handle_signal_quality_change, NULL, NULL);
- g_regex_unref (regex);
-
- regex = g_regex_new ("\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, handle_mode_change, NULL, NULL);
- g_regex_unref (regex);
-
- regex = g_regex_new ("\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, handle_status_change, NULL, NULL);
- g_regex_unref (regex);
-
- regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, NULL, NULL, NULL);
- g_regex_unref (regex);
}
static void
@@ -518,11 +624,16 @@ mm_modem_huawei_get_type (void)
(GInstanceInitFunc) mm_modem_huawei_init,
};
+ static const GInterfaceInfo modem_iface_info = {
+ (GInterfaceInitFunc) modem_init
+ };
+
static const GInterfaceInfo modem_gsm_network_info = {
(GInterfaceInitFunc) modem_gsm_network_init
};
modem_huawei_type = g_type_register_static (MM_TYPE_GENERIC_GSM, "MMModemHuawei", &modem_huawei_type_info, 0);
+ g_type_add_interface_static (modem_huawei_type, MM_TYPE_MODEM, &modem_iface_info);
g_type_add_interface_static (modem_huawei_type, MM_TYPE_MODEM_GSM_NETWORK, &modem_gsm_network_info);
}
diff --git a/plugins/mm-modem-huawei.h b/plugins/mm-modem-huawei.h
index f5154690..16ac99a8 100644
--- a/plugins/mm-modem-huawei.h
+++ b/plugins/mm-modem-huawei.h
@@ -1,16 +1,30 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_MODEM_HUAWEI_H
#define MM_MODEM_HUAWEI_H
#include "mm-generic-gsm.h"
-#define MM_TYPE_MODEM_HUAWEI (mm_modem_huawei_get_type ())
-#define MM_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_HUAWEI, MMModemHuawei))
-#define MM_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiClass))
-#define MM_IS_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_HUAWEI))
-#define MM_IS_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_HUAWEI))
-#define MM_MODEM_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiClass))
+#define MM_TYPE_MODEM_HUAWEI (mm_modem_huawei_get_type ())
+#define MM_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_HUAWEI, MMModemHuawei))
+#define MM_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiClass))
+#define MM_IS_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_HUAWEI))
+#define MM_IS_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_HUAWEI))
+#define MM_MODEM_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiClass))
typedef struct {
MMGenericGsm parent;
@@ -22,8 +36,8 @@ typedef struct {
GType mm_modem_huawei_get_type (void);
-MMModem *mm_modem_huawei_new (const char *data_device,
- const char *monitor_device,
- const char *driver);
+MMModem *mm_modem_huawei_new (const char *device,
+ const char *driver,
+ const char *plugin);
#endif /* MM_MODEM_HUAWEI_H */
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index 69fcc015..4fa22fab 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+
#include "mm-modem-mbm.h"
#include "mm-modem-simple.h"
#include "mm-errors.h"
@@ -39,7 +40,6 @@
#define MBM_E2NAP_CONNECTING 2
#define MBM_SIGNAL_INDICATOR 2
-#define MBM_SEND_DELAY 1000
#define MBM_NETWORK_MODE_ANY 1
#define MBM_NETWORK_MODE_2G 5
@@ -76,12 +76,6 @@ mbm_modem_authenticate (MMModemMbm *self,
const char *password,
gpointer user_data);
-static void
-mbm_set_network_mode_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data);
-
static const char *
mbm_simple_get_string_property (GHashTable *properties, const char *name, GError **error);
@@ -89,21 +83,19 @@ static uint
mbm_simple_get_uint_property (GHashTable *properties, const char *name, GError **error);
MMModem *
-mm_modem_mbm_new (const char *serial_device,
- const char *network_device,
- const char *driver)
+mm_modem_mbm_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (serial_device != NULL, NULL);
- g_return_val_if_fail (network_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_MBM,
- MM_SERIAL_DEVICE, serial_device,
- MM_SERIAL_SEND_DELAY, (guint64) MBM_SEND_DELAY,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_DEVICE, network_device,
+ MM_MODEM_PLUGIN, plugin,
MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_DHCP,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
NULL));
}
@@ -125,14 +117,18 @@ register_done (gpointer user_data)
MMModemMbm *self = MM_MODEM_MBM (reg_data->modem);
MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self);
MMModemGsmNetwork *parent_modem_iface;
+ MMSerialPort *primary;
priv->reg_id = 0;
- mm_serial_queue_command (MM_SERIAL (reg_data->modem), "+CREG=1", 3, NULL, NULL);
- mm_serial_queue_command (MM_SERIAL (reg_data->modem), "+CMER=3,0,0,1", 3, NULL, NULL);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ mm_serial_port_queue_command (primary, "+CREG=1", 3, NULL, NULL);
+ mm_serial_port_queue_command (primary, "+CMER=3,0,0,1", 3, NULL, NULL);
- parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GSM_NETWORK_GET_INTERFACE (reg_data->modem));
- parent_modem_iface->do_register (MM_MODEM_GSM_NETWORK (reg_data->modem),
+ parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GSM_NETWORK_GET_INTERFACE (self));
+ parent_modem_iface->do_register (MM_MODEM_GSM_NETWORK (self),
reg_data->network_id,
reg_data->callback,
reg_data->user_data);
@@ -164,7 +160,10 @@ do_register (MMModemGsmNetwork *modem,
}
static void
-mbm_cind_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
+mbm_cind_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
int quality = 0, ignored;
@@ -186,9 +185,12 @@ get_signal_quality (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "+CIND?", 3, mbm_cind_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "+CIND?", 3, mbm_cind_done, info);
}
static int
@@ -212,6 +214,20 @@ mbm_parse_network_mode (int network_mode)
}
static void
+mbm_set_network_mode_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (error)
+ info->error = g_error_copy (error);
+
+ mm_callback_info_schedule (info);
+}
+
+static void
set_network_mode (MMModemGsmNetwork *modem,
MMModemGsmNetworkMode mode,
MMModemFn callback,
@@ -219,19 +235,22 @@ set_network_mode (MMModemGsmNetwork *modem,
{
MMCallbackInfo *info;
char *command;
+ MMSerialPort *primary;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
command = g_strdup_printf ("+CFUN=%d", mbm_parse_network_mode (mode));
- mm_serial_queue_command (MM_SERIAL (modem), command, 3, mbm_set_network_mode_done, info);
+ mm_serial_port_queue_command (primary, command, 3, mbm_set_network_mode_done, info);
g_free (command);
}
static void
-mbm_get_network_mode_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+get_network_mode_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *erinfo;
@@ -283,9 +302,12 @@ get_network_mode (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "*ERINFO?", 3, mbm_get_network_mode_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "*ERINFO?", 3, get_network_mode_done, info);
}
/*****************************************************************************/
@@ -318,7 +340,10 @@ simple_connect (MMModemSimple *simple,
/*****************************************************************************/
static void
-mbm_enable_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
+mbm_enable_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
@@ -328,10 +353,13 @@ mbm_enable_done (MMSerial *serial, GString *response, GError *error, gpointer us
}
static void
-mbm_init_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
+mbm_init_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (serial);
+ MMCallbackInfo *info = user_data;
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (info->modem);
char *command;
if (error) {
@@ -341,21 +369,25 @@ mbm_init_done (MMSerial *serial, GString *response, GError *error, gpointer user
if (!priv->network_mode)
priv->network_mode = MBM_NETWORK_MODE_ANY;
command = g_strdup_printf ("+CFUN=%d", priv->network_mode);
- mm_serial_queue_command (serial, command, 3, mbm_enable_done, info);
+ mm_serial_port_queue_command (port, command, 3, mbm_enable_done, info);
g_free (command);
}
}
static void
-do_init (MMSerial *serial, gpointer user_data)
+do_init (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "&F E0 V1 X4 &C1 +CMEE=1", 3, mbm_init_done, user_data);
+ mm_serial_port_queue_command (port, "&F E0 V1 X4 &C1 +CMEE=1", 3, mbm_init_done, user_data);
}
static void
-mbm_emrdy_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
+mbm_emrdy_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (serial);
+ MMCallbackInfo *info = user_data;
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (info->modem);
if ( error
&& error->domain == MM_SERIAL_ERROR
@@ -364,39 +396,38 @@ mbm_emrdy_done (MMSerial *serial, GString *response, GError *error, gpointer use
} else
priv->have_emrdy = TRUE;
- do_init (serial, user_data);
+ do_init (port, user_data);
}
static void
-enable_flash_done (MMSerial *serial, gpointer user_data)
+enable_flash_done (MMSerialPort *port, gpointer user_data)
{
- MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (serial);
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMCallbackInfo *info = user_data;
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (info->modem);
if (priv->have_emrdy) {
/* Modem is ready, no need to check EMRDY */
- do_init (serial, info);
+ do_init (port, info);
} else
- mm_serial_queue_command (serial, "*EMRDY?", 5, mbm_emrdy_done, info);
+ mm_serial_port_queue_command (port, "*EMRDY?", 5, mbm_emrdy_done, info);
}
static void
-disable_done (MMSerial *serial,
+disable_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMCallbackInfo *info = user_data;
- mm_serial_close (serial);
+ mm_serial_port_close (port);
mm_callback_info_schedule (info);
}
static void
-disable_flash_done (MMSerial *serial,
- gpointer user_data)
+disable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "+CMER=0", 5, disable_done, user_data);
+ mm_serial_port_queue_command (port, "+CMER=0", 5, disable_done, user_data);
}
static void
@@ -406,24 +437,28 @@ enable (MMModem *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0);
info = mm_callback_info_new (modem, callback, user_data);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
if (do_enable) {
- if (mm_serial_open (MM_SERIAL (modem), &info->error))
- mm_serial_flash (MM_SERIAL (modem), 100, enable_flash_done, info);
+ if (mm_serial_port_open (primary, &info->error))
+ mm_serial_port_flash (primary, 100, enable_flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
} else {
- mm_serial_queue_command (MM_SERIAL (modem), "+CREG=0", 100, NULL, NULL);
+ mm_serial_port_queue_command (primary, "+CREG=0", 100, NULL, NULL);
mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem));
- if (mm_serial_is_connected (MM_SERIAL (modem)))
- mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info);
+ if (mm_serial_port_is_connected (primary))
+ mm_serial_port_flash (primary, 1000, disable_flash_done, info);
else
- disable_flash_done (MM_SERIAL (modem), info);
+ disable_flash_done (primary, info);
}
}
@@ -448,39 +483,27 @@ disconnect (MMModem *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_new (modem, callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "AT*ENAP=0", 3, NULL, info);
-
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "AT*ENAP=0", 3, NULL, info);
mm_callback_info_schedule (info);
}
/*****************************************************************************/
static void
-mbm_set_network_mode_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
-{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- if (error)
- info->error = g_error_copy (error);
-
- mm_callback_info_schedule (info);
-}
-
-static void
-mbm_emrdy_received (MMSerial *serial,
+mbm_emrdy_received (MMSerialPort *port,
GMatchInfo *info,
gpointer user_data)
{
- MM_MODEM_MBM_GET_PRIVATE (serial)->have_emrdy = TRUE;
+ MM_MODEM_MBM_GET_PRIVATE (user_data)->have_emrdy = TRUE;
}
static void
-mbm_pacsp0_received (MMSerial *serial,
+mbm_pacsp0_received (MMSerialPort *port,
GMatchInfo *info,
gpointer user_data)
{
@@ -488,7 +511,7 @@ mbm_pacsp0_received (MMSerial *serial,
}
static void
-mbm_ciev_received (MMSerial *serial,
+mbm_ciev_received (MMSerialPort *port,
GMatchInfo *info,
gpointer user_data)
{
@@ -503,7 +526,7 @@ mbm_ciev_received (MMSerial *serial,
str = g_match_info_fetch (info, 2);
if (str) {
quality = atoi (str);
- mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK(serial), quality * 20);
+ mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (user_data), quality * 20);
}
}
}
@@ -511,13 +534,11 @@ mbm_ciev_received (MMSerial *serial,
static void
mbm_do_connect_done (MMModemMbm *self)
{
- MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self);
-
- mm_callback_info_schedule (priv->do_connect_done_info);
+ mm_callback_info_schedule (MM_MODEM_MBM_GET_PRIVATE (self)->do_connect_done_info);
}
static void
-mbm_e2nap_received (MMSerial *serial,
+mbm_e2nap_received (MMSerialPort *port,
GMatchInfo *info,
gpointer user_data)
{
@@ -532,7 +553,7 @@ mbm_e2nap_received (MMSerial *serial,
g_debug ("%s, disconnected", __func__);
else if (MBM_E2NAP_CONNECTED == state) {
g_debug ("%s, connected", __func__);
- mbm_do_connect_done (MM_MODEM_MBM (serial));
+ mbm_do_connect_done (MM_MODEM_MBM (user_data));
} else if (MBM_E2NAP_CONNECTING == state)
g_debug("%s, connecting", __func__);
else {
@@ -543,7 +564,7 @@ mbm_e2nap_received (MMSerial *serial,
}
static void
-e2nap_done (MMSerial *serial,
+e2nap_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -556,15 +577,15 @@ e2nap_done (MMSerial *serial,
/* TODO: Fallback to polling of enap status */
mm_callback_info_schedule (info);
} else {
- guint32 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (serial));
+ guint32 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (info->modem));
command = g_strdup_printf ("AT*ENAP=1,%d",cid);
- mm_serial_queue_command (serial, command, 3, NULL, NULL);
+ mm_serial_port_queue_command (port, command, 3, NULL, NULL);
g_free (command);
}
}
static void
-mbm_auth_done (MMSerial *serial,
+mbm_auth_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -575,7 +596,7 @@ mbm_auth_done (MMSerial *serial,
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
} else
- mm_serial_queue_command (MM_SERIAL (serial), "AT*E2NAP=1", 3, e2nap_done, user_data);
+ mm_serial_port_queue_command (port, "AT*E2NAP=1", 3, e2nap_done, user_data);
}
static void
@@ -584,6 +605,11 @@ mbm_modem_authenticate (MMModemMbm *self,
const char *password,
gpointer user_data)
{
+ MMSerialPort *primary;
+
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
if (username || password) {
char *command;
@@ -592,10 +618,10 @@ mbm_modem_authenticate (MMModemMbm *self,
username ? username : "",
password ? password : "");
- mm_serial_queue_command (MM_SERIAL (self), command, 3, mbm_auth_done, user_data);
+ mm_serial_port_queue_command (primary, command, 3, mbm_auth_done, user_data);
g_free (command);
} else
- mbm_auth_done (MM_SERIAL (self), NULL, NULL, user_data);
+ mbm_auth_done (primary, NULL, NULL, user_data);
}
static const char *
@@ -638,6 +664,55 @@ mbm_simple_get_uint_property (GHashTable *properties, const char *name, GError *
/*****************************************************************************/
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ MMPort *port = NULL;
+
+ if (!strcmp (subsys, "tty")) {
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY))
+ ptype = MM_PORT_TYPE_SECONDARY;
+ }
+
+ port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
+ if (!port)
+ return FALSE;
+
+ if (MM_IS_SERIAL_PORT (port) && (ptype == MM_PORT_TYPE_PRIMARY)) {
+ GRegex *regex;
+
+ mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (modem), TRUE);
+
+ regex = g_regex_new ("\\r\\n\\*EMRDY: \\d\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_emrdy_received, modem, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_e2nap_received, modem, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_pacsp0_received, modem, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\+CIEV: (\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_ciev_received, modem, NULL);
+ g_regex_unref (regex);
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+
static void
modem_gsm_network_init (MMModemGsmNetwork *class)
{
@@ -656,6 +731,7 @@ modem_simple_init (MMModemSimple *class)
static void
modem_init (MMModem *modem_class)
{
+ modem_class->grab_port = grab_port;
modem_class->enable = enable;
modem_class->connect = do_connect;
modem_class->disconnect = disconnect;
@@ -664,64 +740,6 @@ modem_init (MMModem *modem_class)
static void
mm_modem_mbm_init (MMModemMbm *self)
{
- MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self);
- GRegex *emrdy_regex, *e2nap_regex, *pacsp0_regex, *ciev_regex;
-
- priv->have_emrdy = FALSE;
-
- mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (self), TRUE);
-
- emrdy_regex = g_regex_new ("\\r\\n\\*EMRDY: \\d\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), emrdy_regex, mbm_emrdy_received, self, NULL);
-
- e2nap_regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), e2nap_regex, mbm_e2nap_received, self, NULL);
-
- pacsp0_regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), pacsp0_regex, mbm_pacsp0_received, self, NULL);
-
- ciev_regex = g_regex_new ("\\r\\n\\+CIEV: (\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), ciev_regex, mbm_ciev_received, self, NULL);
-
- g_regex_unref (emrdy_regex);
- g_regex_unref (e2nap_regex);
- g_regex_unref (pacsp0_regex);
- g_regex_unref (ciev_regex);
-}
-
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
-{
- MMModemMbmPrivate *priv;
- GObject *object;
- char *modem_device, *serial_device;
-
- object = G_OBJECT_CLASS (mm_modem_mbm_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
-
- priv = MM_MODEM_MBM_GET_PRIVATE (object);
-
- /* Make sure both serial device and data device are provided */
- g_object_get (object,
- MM_MODEM_DEVICE, &modem_device,
- MM_SERIAL_DEVICE, &serial_device,
- NULL);
-
- if (!modem_device || !serial_device || !strcmp (modem_device, serial_device)) {
- g_warning ("No network device provided");
- g_object_unref (object);
- object = NULL;
- }
-
- g_free (modem_device);
- g_free (serial_device);
-
- return object;
}
static void
@@ -738,36 +756,6 @@ finalize (GObject *object)
}
static void
-set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (object);
-
- switch (prop_id) {
- case PROP_NETWORK_DEVICE:
- /* Construct only */
- priv->network_device = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- switch (prop_id) {
- case PROP_NETWORK_DEVICE:
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
mm_modem_mbm_class_init (MMModemMbmClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -776,9 +764,6 @@ mm_modem_mbm_class_init (MMModemMbmClass *klass)
g_type_class_add_private (object_class, sizeof (MMModemMbmPrivate));
/* Virtual methods */
- object_class->constructor = constructor;
- object_class->set_property = set_property;
- object_class->get_property = get_property;
object_class->finalize = finalize;
}
diff --git a/plugins/mm-modem-mbm.h b/plugins/mm-modem-mbm.h
index aff0bcc4..8756e477 100644
--- a/plugins/mm-modem-mbm.h
+++ b/plugins/mm-modem-mbm.h
@@ -35,8 +35,6 @@
#define MM_IS_MODEM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_MBM))
#define MM_MODEM_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_MBM, MMModemMbmClass))
-#define MM_MODEM_MBM_NETWORK_DEVICE "network-device"
-
typedef struct {
MMGenericGsm parent;
} MMModemMbm;
@@ -47,8 +45,8 @@ typedef struct {
GType mm_modem_mbm_get_type (void);
-MMModem *mm_modem_mbm_new (const char *serial_device,
- const char *network_device,
- const char *driver);
+MMModem *mm_modem_mbm_new (const char *device,
+ const char *driver,
+ const char *plugin_name);
#endif /* MM_MODEM_MBM_H */
diff --git a/plugins/mm-modem-moto-c-gsm.c b/plugins/mm-modem-moto-c-gsm.c
new file mode 100644
index 00000000..cba7b920
--- /dev/null
+++ b/plugins/mm-modem-moto-c-gsm.c
@@ -0,0 +1,158 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mm-modem-moto-c-gsm.h"
+#include "mm-errors.h"
+#include "mm-callback-info.h"
+#include "mm-modem-gsm-card.h"
+
+static gpointer mm_modem_moto_c_gsm_parent_class = NULL;
+
+MMModem *
+mm_modem_moto_c_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin)
+{
+ g_return_val_if_fail (device != NULL, NULL);
+ g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
+
+ return MM_MODEM (g_object_new (MM_TYPE_MODEM_MOTO_C_GSM,
+ MM_MODEM_MASTER_DEVICE, device,
+ MM_MODEM_DRIVER, driver,
+ MM_MODEM_PLUGIN, plugin,
+ NULL));
+}
+
+/*****************************************************************************/
+
+static void
+modem_init (MMModem *modem_class)
+{
+}
+
+/*****************************************************************************/
+
+static void
+get_imei (MMModemGsmCard *modem,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_string_new (MM_MODEM (modem), 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
+modem_gsm_card_init (MMModemGsmCard *class)
+{
+ class->get_imei = get_imei;
+}
+
+/*****************************************************************************/
+
+static void
+mm_modem_moto_c_gsm_init (MMModemMotoCGsm *self)
+{
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+
+ /* These devices just don't implement AT+CFUN */
+
+ switch (prop_id) {
+ case MM_GENERIC_GSM_PROP_POWER_UP_CMD:
+ g_value_set_string (value, "");
+ break;
+ case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
+ g_value_set_string (value, "");
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+}
+
+static void
+mm_modem_moto_c_gsm_class_init (MMModemMotoCGsmClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ mm_modem_moto_c_gsm_parent_class = g_type_class_peek_parent (klass);
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+
+ g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_POWER_UP_CMD,
+ MM_GENERIC_GSM_POWER_UP_CMD);
+
+ g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_POWER_DOWN_CMD,
+ MM_GENERIC_GSM_POWER_DOWN_CMD);
+}
+
+GType
+mm_modem_moto_c_gsm_get_type (void)
+{
+ static GType modem_moto_c_gsm_type = 0;
+
+ if (G_UNLIKELY (modem_moto_c_gsm_type == 0)) {
+ static const GTypeInfo modem_moto_c_gsm_type_info = {
+ sizeof (MMModemMotoCGsmClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mm_modem_moto_c_gsm_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (MMModemMotoCGsm),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mm_modem_moto_c_gsm_init,
+ };
+
+ static const GInterfaceInfo modem_iface_info = {
+ (GInterfaceInitFunc) modem_init
+ };
+
+ static const GInterfaceInfo modem_gsm_card_info = {
+ (GInterfaceInitFunc) modem_gsm_card_init
+ };
+
+ modem_moto_c_gsm_type = g_type_register_static (MM_TYPE_GENERIC_GSM, "MMModemMotoCGsm",
+ &modem_moto_c_gsm_type_info, 0);
+
+ g_type_add_interface_static (modem_moto_c_gsm_type, MM_TYPE_MODEM, &modem_iface_info);
+ g_type_add_interface_static (modem_moto_c_gsm_type, MM_TYPE_MODEM_GSM_CARD, &modem_gsm_card_info);
+ }
+
+ return modem_moto_c_gsm_type;
+}
diff --git a/plugins/mm-modem-moto-c-gsm.h b/plugins/mm-modem-moto-c-gsm.h
new file mode 100644
index 00000000..eb1dad12
--- /dev/null
+++ b/plugins/mm-modem-moto-c-gsm.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_MODEM_MOTO_C_GSM_H
+#define MM_MODEM_MOTO_C_GSM_H
+
+#include "mm-generic-gsm.h"
+
+#define MM_TYPE_MODEM_MOTO_C_GSM (mm_modem_moto_c_gsm_get_type ())
+#define MM_MODEM_MOTO_C_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_MOTO_C_GSM, MMModemMotoCGsm))
+#define MM_MODEM_MOTO_C_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_MOTO_C_GSM, MMModemMotoCGsmClass))
+#define MM_IS_MODEM_MOTO_C_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_MOTO_C_GSM))
+#define MM_IS_MODEM_MOTO_C_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_MOTO_C_GSM))
+#define MM_MODEM_MOTO_C_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_MOTO_C_GSM, MMModemMotoCGsmClass))
+
+typedef struct {
+ MMGenericGsm parent;
+} MMModemMotoCGsm;
+
+typedef struct {
+ MMGenericGsmClass parent;
+} MMModemMotoCGsmClass;
+
+GType mm_modem_moto_c_gsm_get_type (void);
+
+MMModem *mm_modem_moto_c_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin_name);
+
+#endif /* MM_MODEM_MOTO_C_GSM_H */
diff --git a/plugins/mm-modem-nokia.c b/plugins/mm-modem-nokia.c
index 8a81cbeb..a37c1143 100644
--- a/plugins/mm-modem-nokia.c
+++ b/plugins/mm-modem-nokia.c
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <stdlib.h>
#include <stdio.h>
@@ -10,28 +24,59 @@
static gpointer mm_modem_nokia_parent_class = NULL;
MMModem *
-mm_modem_nokia_new (const char *data_device,
- const char *driver)
+mm_modem_nokia_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (data_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_NOKIA,
- MM_SERIAL_DEVICE, data_device,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ MMPort *port = NULL;
+
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY))
+ ptype = MM_PORT_TYPE_SECONDARY;
+
+ port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
+ if (port && MM_IS_SERIAL_PORT (port)) {
+ mm_serial_port_set_response_parser (MM_SERIAL_PORT (port),
+ mm_serial_parser_v1_e1_parse,
+ mm_serial_parser_v1_e1_new (),
+ mm_serial_parser_v1_e1_destroy);
+ }
+
+ return !!port;
+}
+
/*****************************************************************************/
static void
+modem_init (MMModem *modem_class)
+{
+ modem_class->grab_port = grab_port;
+}
+
+static void
mm_modem_nokia_init (MMModemNokia *self)
{
- mm_serial_set_response_parser (MM_SERIAL (self),
- mm_serial_parser_v1_e1_parse,
- mm_serial_parser_v1_e1_new (),
- mm_serial_parser_v1_e1_destroy);
}
static void
@@ -58,7 +103,13 @@ mm_modem_nokia_get_type (void)
(GInstanceInitFunc) mm_modem_nokia_init,
};
+ static const GInterfaceInfo modem_iface_info = {
+ (GInterfaceInitFunc) modem_init
+ };
+
modem_nokia_type = g_type_register_static (MM_TYPE_GENERIC_GSM, "MMModemNokia", &modem_nokia_type_info, 0);
+
+ g_type_add_interface_static (modem_nokia_type, MM_TYPE_MODEM, &modem_iface_info);
}
return modem_nokia_type;
diff --git a/plugins/mm-modem-nokia.h b/plugins/mm-modem-nokia.h
index b287b164..0e24619f 100644
--- a/plugins/mm-modem-nokia.h
+++ b/plugins/mm-modem-nokia.h
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_MODEM_NOKIA_H
#define MM_MODEM_NOKIA_H
@@ -22,7 +36,8 @@ typedef struct {
GType mm_modem_nokia_get_type (void);
-MMModem *mm_modem_nokia_new (const char *data_device,
- const char *driver);
+MMModem *mm_modem_nokia_new (const char *data,
+ const char *driver,
+ const char *plugin);
#endif /* MM_MODEM_NOKIA_H */
diff --git a/plugins/mm-modem-novatel-cdma.c b/plugins/mm-modem-novatel-cdma.c
deleted file mode 100644
index 4b6b9b2e..00000000
--- a/plugins/mm-modem-novatel-cdma.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include "mm-modem-novatel-cdma.h"
-#include "mm-errors.h"
-#include "mm-callback-info.h"
-
-static gpointer mm_modem_novatel_cdma_parent_class = NULL;
-
-MMModem *
-mm_modem_novatel_cdma_new (const char *data_device,
- const char *driver)
-{
- g_return_val_if_fail (data_device != NULL, NULL);
- g_return_val_if_fail (driver != NULL, NULL);
-
- return MM_MODEM (g_object_new (MM_TYPE_MODEM_NOVATEL_CDMA,
- MM_SERIAL_DEVICE, data_device,
- MM_SERIAL_CARRIER_DETECT, FALSE,
- MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_CDMA,
- NULL));
-}
-
-/*****************************************************************************/
-
-static void
-modem_init (MMModem *modem_class)
-{
-}
-
-static void
-mm_modem_novatel_cdma_init (MMModemNovatelCdma *self)
-{
-}
-
-static void
-mm_modem_novatel_cdma_class_init (MMModemNovatelCdmaClass *klass)
-{
- mm_modem_novatel_cdma_parent_class = g_type_class_peek_parent (klass);
-}
-
-GType
-mm_modem_novatel_cdma_get_type (void)
-{
- static GType modem_novatel_cdma_type = 0;
-
- if (G_UNLIKELY (modem_novatel_cdma_type == 0)) {
- static const GTypeInfo modem_novatel_cdma_type_info = {
- sizeof (MMModemNovatelCdmaClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) mm_modem_novatel_cdma_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (MMModemNovatelCdma),
- 0, /* n_preallocs */
- (GInstanceInitFunc) mm_modem_novatel_cdma_init,
- };
-
- static const GInterfaceInfo modem_iface_info = {
- (GInterfaceInitFunc) modem_init
- };
-
- modem_novatel_cdma_type = g_type_register_static (MM_TYPE_GENERIC_CDMA, "MMModemNovatelCdma", &modem_novatel_cdma_type_info, 0);
- g_type_add_interface_static (modem_novatel_cdma_type, MM_TYPE_MODEM, &modem_iface_info);
- }
-
- return modem_novatel_cdma_type;
-}
diff --git a/plugins/mm-modem-novatel-cdma.h b/plugins/mm-modem-novatel-cdma.h
deleted file mode 100644
index d9b9d33a..00000000
--- a/plugins/mm-modem-novatel-cdma.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-
-#ifndef MM_MODEM_NOVATEL_CDMA_H
-#define MM_MODEM_NOVATEL_CDMA_H
-
-#include "mm-generic-cdma.h"
-
-#define MM_TYPE_MODEM_NOVATEL_CDMA (mm_modem_novatel_cdma_get_type ())
-#define MM_MODEM_NOVATEL_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_NOVATEL_CDMA, MMModemNovatelCdma))
-#define MM_MODEM_NOVATEL_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_NOVATEL_CDMA, MMModemNovatelCdmaClass))
-#define MM_IS_MODEM_NOVATEL_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_NOVATEL_CDMA))
-#define MM_IS_MODEM_NOVATEL_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_NOVATEL_CDMA))
-#define MM_MODEM_NOVATEL_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_NOVATEL_CDMA, MMModemNovatelCdmaClass))
-
-typedef struct {
- MMGenericCdma parent;
-} MMModemNovatelCdma;
-
-typedef struct {
- MMGenericCdmaClass parent;
-} MMModemNovatelCdmaClass;
-
-GType mm_modem_novatel_cdma_get_type (void);
-
-MMModem *mm_modem_novatel_cdma_new (const char *data_device,
- const char *driver);
-
-#endif /* MM_MODEM_NOVATEL_CDMA_H */
diff --git a/plugins/mm-modem-novatel-gsm.c b/plugins/mm-modem-novatel-gsm.c
index 9c569264..265810c3 100644
--- a/plugins/mm-modem-novatel-gsm.c
+++ b/plugins/mm-modem-novatel-gsm.c
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <stdlib.h>
#include <stdio.h>
@@ -11,16 +25,18 @@
static gpointer mm_modem_novatel_gsm_parent_class = NULL;
MMModem *
-mm_modem_novatel_gsm_new (const char *data_device,
- const char *driver)
+mm_modem_novatel_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (data_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_NOVATEL_GSM,
- MM_SERIAL_DEVICE, data_device,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
@@ -29,7 +45,7 @@ mm_modem_novatel_gsm_new (const char *data_device,
/*****************************************************************************/
static void
-init_modem_done (MMSerial *serial,
+init_modem_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -46,17 +62,21 @@ static void
pin_check_done (MMModem *modem, GError *error, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMSerialPort *primary;
if (error) {
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
- } else
+ } else {
/* Finish the initialization */
- mm_serial_queue_command (MM_SERIAL (modem), "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1", 10, init_modem_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1", 10, init_modem_done, info);
+ }
}
static void
-pre_init_done (MMSerial *serial,
+pre_init_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -74,25 +94,25 @@ pre_init_done (MMSerial *serial,
}
static void
-enable_flash_done (MMSerial *serial, gpointer user_data)
+enable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "E0 V1", 3, pre_init_done, user_data);
+ mm_serial_port_queue_command (port, "E0 V1", 3, pre_init_done, user_data);
}
static void
-disable_done (MMSerial *serial,
+disable_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
- mm_serial_close (serial);
+ mm_serial_port_close (port);
mm_callback_info_schedule ((MMCallbackInfo *) user_data);
}
static void
-disable_flash_done (MMSerial *serial, gpointer user_data)
+disable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "+CFUN=0", 5, disable_done, user_data);
+ mm_serial_port_queue_command (port, "+CFUN=0", 5, disable_done, user_data);
}
static void
@@ -102,32 +122,75 @@ enable (MMModem *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
/* First, reset the previously used CID */
mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0);
info = mm_callback_info_new (modem, callback, user_data);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
if (!do_enable) {
- if (mm_serial_is_connected (MM_SERIAL (modem)))
- mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info);
+ if (mm_serial_port_is_connected (primary))
+ mm_serial_port_flash (primary, 1000, disable_flash_done, info);
else
- disable_flash_done (MM_SERIAL (modem), info);
+ disable_flash_done (primary, info);
} else {
- if (mm_serial_open (MM_SERIAL (modem), &info->error))
- mm_serial_flash (MM_SERIAL (modem), 100, enable_flash_done, info);
+ if (mm_serial_port_open (primary, &info->error))
+ mm_serial_port_flash (primary, 100, enable_flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
}
}
+static void
+dmat_callback (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ mm_serial_port_close (port);
+}
+
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ MMPort *port = NULL;
+
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY))
+ ptype = MM_PORT_TYPE_SECONDARY;
+
+ port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
+ if (!port)
+ return FALSE;
+
+ if (MM_IS_SERIAL_PORT (port) && (ptype == MM_PORT_TYPE_PRIMARY)) {
+ /* Flip secondary ports to AT mode */
+ if (mm_serial_port_open (MM_SERIAL_PORT (port), NULL))
+ mm_serial_port_queue_command (MM_SERIAL_PORT (port), "$NWDMAT=1", 2, dmat_callback, NULL);
+ }
+
+ return !!port;
+}
+
/*****************************************************************************/
static void
modem_init (MMModem *modem_class)
{
modem_class->enable = enable;
+ modem_class->grab_port = grab_port;
}
static void
diff --git a/plugins/mm-modem-novatel-gsm.h b/plugins/mm-modem-novatel-gsm.h
index cfb0c007..c2e11387 100644
--- a/plugins/mm-modem-novatel-gsm.h
+++ b/plugins/mm-modem-novatel-gsm.h
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_MODEM_NOVATEL_GSM_H
#define MM_MODEM_NOVATEL_GSM_H
@@ -22,7 +36,8 @@ typedef struct {
GType mm_modem_novatel_gsm_get_type (void);
-MMModem *mm_modem_novatel_gsm_new (const char *data_device,
- const char *driver);
+MMModem *mm_modem_novatel_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin_name);
#endif /* MM_MODEM_NOVATEL_GSM_H */
diff --git a/plugins/mm-modem-option.c b/plugins/mm-modem-option.c
index 0c77c892..f0a3bcbf 100644
--- a/plugins/mm-modem-option.c
+++ b/plugins/mm-modem-option.c
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <stdlib.h>
#include <stdio.h>
@@ -11,19 +25,23 @@
static gpointer mm_modem_option_parent_class = NULL;
MMModem *
-mm_modem_option_new (const char *data_device,
- const char *driver)
+mm_modem_option_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (data_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_OPTION,
- MM_SERIAL_DEVICE, data_device,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
+/*****************************************************************************/
+
static void
pin_check_done (MMModem *modem, GError *error, gpointer user_data)
{
@@ -80,7 +98,7 @@ enable (MMModem *modem,
}
static void
-get_network_mode_done (MMSerial *serial,
+get_network_mode_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -131,13 +149,16 @@ get_network_mode (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "AT_OPSYS?", 3, get_network_mode_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "AT_OPSYS?", 3, get_network_mode_done, info);
}
static void
-set_network_mode_done (MMSerial *serial,
+set_network_mode_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -157,6 +178,7 @@ set_network_mode (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
char *command;
int i;
@@ -188,7 +210,9 @@ set_network_mode (MMModemGsmNetwork *modem,
}
command = g_strdup_printf ("AT_OPSYS=%d,2", i);
- mm_serial_queue_command (MM_SERIAL (modem), command, 3, set_network_mode_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, command, 3, set_network_mode_done, info);
g_free (command);
}
diff --git a/plugins/mm-modem-option.h b/plugins/mm-modem-option.h
index 386be455..4e88607e 100644
--- a/plugins/mm-modem-option.h
+++ b/plugins/mm-modem-option.h
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_MODEM_OPTION_H
#define MM_MODEM_OPTION_H
@@ -22,7 +36,8 @@ typedef struct {
GType mm_modem_option_get_type (void);
-MMModem *mm_modem_option_new (const char *data_device,
- const char *driver);
+MMModem *mm_modem_option_new (const char *device,
+ const char *driver,
+ const char *plugin_name);
#endif /* MM_MODEM_OPTION_H */
diff --git a/plugins/mm-modem-sierra.c b/plugins/mm-modem-sierra.c
index 4040ed84..69a7af30 100644
--- a/plugins/mm-modem-sierra.c
+++ b/plugins/mm-modem-sierra.c
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <stdlib.h>
#include <stdio.h>
@@ -11,16 +25,18 @@
static gpointer mm_modem_sierra_parent_class = NULL;
MMModem *
-mm_modem_sierra_new (const char *data_device,
- const char *driver)
+mm_modem_sierra_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (data_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_SIERRA,
- MM_SERIAL_DEVICE, data_device,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
@@ -51,7 +67,7 @@ sierra_enabled (gpointer data)
}
static void
-init_done (MMSerial *serial,
+init_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -68,15 +84,15 @@ init_done (MMSerial *serial,
}
static void
-enable_flash_done (MMSerial *serial, gpointer user_data)
+enable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "Z E0 V1 X4 &C1 +CMEE=1", 3, init_done, user_data);
+ mm_serial_port_queue_command (port, "Z E0 V1 X4 &C1 +CMEE=1", 3, init_done, user_data);
}
static void
-disable_flash_done (MMSerial *serial, gpointer user_data)
+disable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_close (serial);
+ mm_serial_port_close (port);
mm_callback_info_schedule ((MMCallbackInfo *) user_data);
}
@@ -87,6 +103,7 @@ enable (MMModem *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
/* First, reset the previously used CID */
mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0);
@@ -94,25 +111,58 @@ enable (MMModem *modem,
info = mm_callback_info_new (modem, callback, user_data);
mm_callback_info_set_data (info, "sierra-enable", GINT_TO_POINTER (do_enable), NULL);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
if (!do_enable) {
- if (mm_serial_is_connected (MM_SERIAL (modem)))
- mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info);
+ if (mm_serial_port_is_connected (primary))
+ mm_serial_port_flash (primary, 1000, disable_flash_done, info);
else
- disable_flash_done (MM_SERIAL (modem), info);
+ disable_flash_done (primary, info);
} else {
- if (mm_serial_open (MM_SERIAL (modem), &info->error))
- mm_serial_flash (MM_SERIAL (modem), 100, enable_flash_done, info);
+ if (mm_serial_port_open (primary, &info->error))
+ mm_serial_port_flash (primary, 100, enable_flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
}
}
+
+/* user_data != NULL means the port is a secondary port */
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ MMPort *port;
+
+ if (user_data) {
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY))
+ ptype = MM_PORT_TYPE_SECONDARY;
+ } else {
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ }
+
+ port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
+
+ if (port && MM_IS_SERIAL_PORT (port))
+ g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL);
+
+ return !!port;
+}
+
/*****************************************************************************/
static void
modem_init (MMModem *modem_class)
{
modem_class->enable = enable;
+ modem_class->grab_port = grab_port;
}
static void
diff --git a/plugins/mm-modem-sierra.h b/plugins/mm-modem-sierra.h
index 6e95b984..308eb494 100644
--- a/plugins/mm-modem-sierra.h
+++ b/plugins/mm-modem-sierra.h
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_MODEM_SIERRA_H
#define MM_MODEM_SIERRA_H
@@ -22,7 +36,8 @@ typedef struct {
GType mm_modem_sierra_get_type (void);
-MMModem *mm_modem_sierra_new (const char *data_device,
- const char *driver);
+MMModem *mm_modem_sierra_new (const char *device,
+ const char *driver,
+ const char *plugin_name);
#endif /* MM_MODEM_SIERRA_H */
diff --git a/plugins/mm-modem-zte.c b/plugins/mm-modem-zte.c
index 28c74ad6..f2c0a342 100644
--- a/plugins/mm-modem-zte.c
+++ b/plugins/mm-modem-zte.c
@@ -1,26 +1,43 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "mm-modem-zte.h"
-#include "mm-serial.h"
+#include "mm-serial-port.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
static gpointer mm_modem_zte_parent_class = NULL;
MMModem *
-mm_modem_zte_new (const char *data_device,
- const char *driver)
+mm_modem_zte_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (data_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_MODEM_ZTE,
- MM_SERIAL_DEVICE, data_device,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
@@ -29,7 +46,7 @@ mm_modem_zte_new (const char *data_device,
/*****************************************************************************/
static void
-init_modem_done (MMSerial *serial,
+init_modem_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -46,17 +63,21 @@ static void
pin_check_done (MMModem *modem, GError *error, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMSerialPort *primary;
if (error) {
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
- } else
+ } else {
/* Finish the initialization */
- mm_serial_queue_command (MM_SERIAL (modem), "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;", 10, init_modem_done, info);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+ mm_serial_port_queue_command (primary, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;", 10, init_modem_done, info);
+ }
}
static void
-pre_init_done (MMSerial *serial,
+pre_init_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -74,25 +95,25 @@ pre_init_done (MMSerial *serial,
}
static void
-enable_flash_done (MMSerial *serial, gpointer user_data)
+enable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "E0 V1", 3, pre_init_done, user_data);
+ mm_serial_port_queue_command (port, "E0 V1", 3, pre_init_done, user_data);
}
static void
-disable_done (MMSerial *serial,
+disable_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
- mm_serial_close (serial);
+ mm_serial_port_close (port);
mm_callback_info_schedule ((MMCallbackInfo *) user_data);
}
static void
-disable_flash_done (MMSerial *serial, gpointer user_data)
+disable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "+CFUN=0", 5, disable_done, user_data);
+ mm_serial_port_queue_command (port, "+CFUN=0", 5, disable_done, user_data);
}
static void
@@ -102,57 +123,85 @@ enable (MMModem *modem,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMSerialPort *primary;
/* First, reset the previously used CID */
mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0);
info = mm_callback_info_new (modem, callback, user_data);
+ primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
if (!do_enable) {
- if (mm_serial_is_connected (MM_SERIAL (modem)))
- mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info);
+ if (mm_serial_port_is_connected (primary))
+ mm_serial_port_flash (primary, 1000, disable_flash_done, info);
else
- disable_flash_done (MM_SERIAL (modem), info);
+ disable_flash_done (primary, info);
} else {
- if (mm_serial_open (MM_SERIAL (modem), &info->error))
- mm_serial_flash (MM_SERIAL (modem), 100, enable_flash_done, info);
+ if (mm_serial_port_open (primary, &info->error))
+ mm_serial_port_flash (primary, 100, enable_flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
}
}
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ MMPort *port = NULL;
+
+ if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY))
+ ptype = MM_PORT_TYPE_SECONDARY;
+
+ port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
+ if (port && MM_IS_SERIAL_PORT (port)) {
+ GRegex *regex;
+
+ mm_generic_gsm_set_unsolicited_registration (gsm, TRUE);
+ g_object_set (port, MM_PORT_CARRIER_DETECT, FALSE, NULL);
+
+ regex = g_regex_new ("\\r\\n\\+ZUSIMR:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\+ZDONR: (.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\+ZPASR: (.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL);
+ g_regex_unref (regex);
+
+ regex = g_regex_new ("\\r\\n\\+ZEND\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL);
+ g_regex_unref (regex);
+ }
+
+ return !!port;
+}
+
/*****************************************************************************/
static void
modem_init (MMModem *modem_class)
{
modem_class->enable = enable;
+ modem_class->grab_port = grab_port;
}
static void
mm_modem_zte_init (MMModemZte *self)
{
- GRegex *regex;
-
- mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (self), TRUE);
- g_object_set (G_OBJECT (self), MM_SERIAL_CARRIER_DETECT, FALSE, NULL);
-
- regex = g_regex_new ("\\r\\n\\+ZUSIMR:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, NULL, NULL, NULL);
- g_regex_unref (regex);
-
- regex = g_regex_new ("\\r\\n\\+ZDONR: (.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, NULL, NULL, NULL);
- g_regex_unref (regex);
-
- regex = g_regex_new ("\\r\\n\\+ZPASR: (.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, NULL, NULL, NULL);
- g_regex_unref (regex);
-
- regex = g_regex_new ("\\r\\n\\+ZEND\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, NULL, NULL, NULL);
- g_regex_unref (regex);
}
static void
diff --git a/plugins/mm-modem-zte.h b/plugins/mm-modem-zte.h
index 285dc938..112bae00 100644
--- a/plugins/mm-modem-zte.h
+++ b/plugins/mm-modem-zte.h
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_MODEM_ZTE_H
#define MM_MODEM_ZTE_H
@@ -22,7 +36,8 @@ typedef struct {
GType mm_modem_zte_get_type (void);
-MMModem *mm_modem_zte_new (const char *data_device,
- const char *driver);
+MMModem *mm_modem_zte_new (const char *device,
+ const char *driver,
+ const char *plugin);
#endif /* MM_MODEM_ZTE_H */
diff --git a/plugins/mm-plugin-generic.c b/plugins/mm-plugin-generic.c
new file mode 100644
index 00000000..208a61f2
--- /dev/null
+++ b/plugins/mm-plugin-generic.c
@@ -0,0 +1,179 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Dan Williams <dcbw@redhat.com>
+ */
+
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <time.h>
+
+#include <gmodule.h>
+
+#include "mm-plugin-generic.h"
+#include "mm-generic-gsm.h"
+#include "mm-generic-cdma.h"
+#include "mm-errors.h"
+#include "mm-serial-parsers.h"
+
+G_DEFINE_TYPE (MMPluginGeneric, mm_plugin_generic, MM_TYPE_PLUGIN_BASE)
+
+int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
+int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
+
+G_MODULE_EXPORT MMPlugin *
+mm_plugin_create (void)
+{
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_GENERIC,
+ MM_PLUGIN_BASE_NAME, MM_PLUGIN_GENERIC_NAME,
+ NULL));
+}
+
+/*****************************************************************************/
+
+#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
+
+static guint32
+get_level_for_capabilities (guint32 capabilities)
+{
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 5;
+ if (capabilities & CAP_CDMA)
+ return 5;
+ return 0;
+}
+
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
+{
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
+}
+
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
+{
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
+
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+}
+
+static MMModem *
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
+{
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *devfile, *sysfs_path;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ devfile = g_udev_device_get_device_file (port);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ return NULL;
+ }
+
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ modem = mm_generic_gsm_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ } else if (caps & CAP_CDMA) {
+ modem = mm_generic_cdma_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
+
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ if (caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
+ }
+ }
+
+ return modem;
+}
+
+/*****************************************************************************/
+
+static void
+mm_plugin_generic_init (MMPluginGeneric *self)
+{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
+}
+
+static void
+mm_plugin_generic_class_init (MMPluginGenericClass *klass)
+{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
+}
+
diff --git a/plugins/mm-plugin-generic.h b/plugins/mm-plugin-generic.h
new file mode 100644
index 00000000..35502af6
--- /dev/null
+++ b/plugins/mm-plugin-generic.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+#ifndef MM_PLUGIN_GENERIC_H
+#define MM_PLUGIN_GENERIC_H
+
+#include "mm-plugin.h"
+#include "mm-plugin-base.h"
+
+#define MM_TYPE_PLUGIN_GENERIC (mm_plugin_generic_get_type ())
+#define MM_PLUGIN_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_GENERIC, MMPluginGeneric))
+#define MM_PLUGIN_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_GENERIC, MMPluginGenericClass))
+#define MM_IS_PLUGIN_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_GENERIC))
+#define MM_IS_PLUGIN_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_GENERIC))
+#define MM_PLUGIN_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_GENERIC, MMPluginGenericClass))
+
+typedef struct {
+ MMPluginBase parent;
+} MMPluginGeneric;
+
+typedef struct {
+ MMPluginBaseClass parent;
+} MMPluginGenericClass;
+
+GType mm_plugin_generic_get_type (void);
+
+G_MODULE_EXPORT MMPlugin *mm_plugin_create (void);
+
+#endif /* MM_PLUGIN_GENERIC_H */
diff --git a/plugins/mm-plugin-gobi.c b/plugins/mm-plugin-gobi.c
new file mode 100644
index 00000000..6e5bfd9c
--- /dev/null
+++ b/plugins/mm-plugin-gobi.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <gmodule.h>
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
+#include "mm-plugin-gobi.h"
+#include "mm-modem-gobi-gsm.h"
+#include "mm-generic-cdma.h"
+
+G_DEFINE_TYPE (MMPluginGobi, mm_plugin_gobi, MM_TYPE_PLUGIN_BASE)
+
+int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
+int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
+
+G_MODULE_EXPORT MMPlugin *
+mm_plugin_create (void)
+{
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_GOBI,
+ MM_PLUGIN_BASE_NAME, "Gobi",
+ NULL));
+}
+
+/*****************************************************************************/
+
+#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
+
+static guint32
+get_level_for_capabilities (guint32 capabilities)
+{
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ if (capabilities & CAP_CDMA)
+ return 10;
+ return 0;
+}
+
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
+{
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
+}
+
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
+{
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ const char *driver;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (!driver || strcmp (driver, "qcserial"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
+
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+}
+
+static MMModem *
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
+{
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *sysfs_path;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ modem = mm_modem_gobi_gsm_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ } else if (caps & CAP_CDMA) {
+ modem = mm_generic_cdma_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
+
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ if (caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
+ }
+ }
+
+ return modem;
+}
+
+/*****************************************************************************/
+
+static void
+mm_plugin_gobi_init (MMPluginGobi *self)
+{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
+}
+
+static void
+mm_plugin_gobi_class_init (MMPluginGobiClass *klass)
+{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
+}
+
diff --git a/plugins/mm-plugin-gobi.h b/plugins/mm-plugin-gobi.h
new file mode 100644
index 00000000..aceba6b0
--- /dev/null
+++ b/plugins/mm-plugin-gobi.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_PLUGIN_GOBI_H
+#define MM_PLUGIN_GOBI_H
+
+#include "mm-plugin.h"
+#include "mm-plugin-base.h"
+#include "mm-generic-gsm.h"
+
+#define MM_TYPE_PLUGIN_GOBI (mm_plugin_gobi_get_type ())
+#define MM_PLUGIN_GOBI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_GOBI, MMPluginGobi))
+#define MM_PLUGIN_GOBI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_GOBI, MMPluginGobiClass))
+#define MM_IS_PLUGIN_GOBI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_GOBI))
+#define MM_IS_PLUGIN_GOBI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_GOBI))
+#define MM_PLUGIN_GOBI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_GOBI, MMPluginGobiClass))
+
+typedef struct {
+ MMPluginBase parent;
+} MMPluginGobi;
+
+typedef struct {
+ MMPluginBaseClass parent;
+} MMPluginGobiClass;
+
+GType mm_plugin_gobi_get_type (void);
+
+G_MODULE_EXPORT MMPlugin *mm_plugin_create (void);
+
+#endif /* MM_PLUGIN_GOBI_H */
+
diff --git a/plugins/mm-plugin-hso.c b/plugins/mm-plugin-hso.c
index ce280759..b038b5ef 100644
--- a/plugins/mm-plugin-hso.c
+++ b/plugins/mm-plugin-hso.c
@@ -1,242 +1,182 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <string.h>
#include <gmodule.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
#include "mm-plugin-hso.h"
#include "mm-modem-hso.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginHso, mm_plugin_hso, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginHso, mm_plugin_hso, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
+
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_HSO, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_HSO,
+ MM_PLUGIN_BASE_NAME, "Option High-Speed",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- return "HSO";
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ return 0;
}
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
-
- devices = libhal_find_device_by_capability (hal_ctx, "serial", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
+}
- array = g_ptr_array_new ();
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
+{
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ const char *driver, *subsys;
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
+ port = mm_plugin_base_supports_task_get_port (task);
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
- }
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (!driver || strcmp (driver, "hso"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
+ subsys = g_udev_device_get_subsystem (port);
+ g_assert (subsys);
+ if (!strcmp (subsys, "net")) {
+ mm_plugin_base_supports_task_complete (task, 10);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
}
- g_strfreev (devices);
-
- return supported;
-}
-
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
-{
- char *parent_udi;
- char *driver = NULL;
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
- }
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
- return driver;
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
-static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+static MMModem *
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *driver_name;
- gboolean supported = FALSE;
-
- driver_name = get_driver_name (hal_ctx, udi);
- if (driver_name && !strcmp (driver_name, "hso")) {
- char *sysfs_path;
-
- sysfs_path = libhal_device_get_property_string (hal_ctx, udi, "linux.sysfs_path", NULL);
- if (sysfs_path) {
- char *hso_type_path;
- gchar *contents = NULL;
- gsize length;
-
- hso_type_path = g_build_filename (sysfs_path, "hsotype", NULL);
- libhal_free_string (sysfs_path);
-
- if (g_file_get_contents (hso_type_path, &contents, &length, NULL)) {
- if (g_str_has_prefix (contents, "Control"))
- supported = TRUE;
-
- g_free (contents);
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *sysfs_path;
+ char *devfile;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ devfile = g_strdup (g_udev_device_get_device_file (port));
+ if (!devfile) {
+ if (!strcmp (subsys, "net")) {
+ /* Apparently 'hso' doesn't set up the right links for the netdevice,
+ * and thus libgudev can't get the sysfs file path for it.
+ */
+ devfile = g_strdup_printf ("/sys/class/net/%s", name);
+ if (!g_file_test (devfile, G_FILE_TEST_EXISTS)) {
+ g_free (devfile);
+ devfile = NULL;
}
+ }
- g_free (hso_type_path);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ goto out;
}
}
- libhal_free_string (driver_name);
-
- return supported;
-}
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ goto out;
+ }
-static char *
-get_netdev (LibHalContext *ctx, const char *udi)
-{
- char *serial_parent, *netdev = NULL;
- char **netdevs;
- int num, i;
-
- /* Get the serial interface's originating device UDI, used to find the
- * originating device's netdev.
- */
- serial_parent = libhal_device_get_property_string (ctx, udi, "serial.originating_device", NULL);
- if (!serial_parent)
- serial_parent = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (!serial_parent)
- return NULL;
-
- /* Look for the originating device's netdev */
- netdevs = libhal_find_device_by_capability (ctx, "net", &num, NULL);
- for (i = 0; netdevs && !netdev && (i < num); i++) {
- char *netdev_parent, *tmp;
-
- netdev_parent = libhal_device_get_property_string (ctx, netdevs[i], "net.originating_device", NULL);
- if (!netdev_parent)
- netdev_parent = libhal_device_get_property_string (ctx, netdevs[i], "net.physical_device", NULL);
- if (!netdev_parent)
- continue;
-
- if (!strcmp (netdev_parent, serial_parent)) {
- /* We found it */
- tmp = libhal_device_get_property_string (ctx, netdevs[i], "net.interface", NULL);
- if (tmp) {
- netdev = g_strdup (tmp);
- libhal_free_string (tmp);
- }
- }
-
- libhal_free_string (netdev_parent);
- }
-
- if (!netdev) {
- /* Didn't find from netdev's parents. Try again with "grandparents" */
- char *serial_grandparent;
-
- serial_grandparent = libhal_device_get_property_string (ctx, serial_parent, "info.parent", NULL);
- if (!serial_grandparent)
- goto cleanup;
-
- for (i = 0; netdevs && !netdev && (i < num); i++) {
- char *netdev_parent, *tmp;
-
- tmp = libhal_device_get_property_string (ctx, netdevs[i], "net.originating_device", NULL);
- if (!tmp)
- tmp = libhal_device_get_property_string (ctx, netdevs[i], "net.physical_device", NULL);
- if (!tmp)
- tmp = libhal_device_get_property_string (ctx, netdevs[i], "info.parent", NULL);
- if (!tmp)
- continue;
-
- netdev_parent = libhal_device_get_property_string (ctx, tmp, "info.parent", NULL);
- libhal_free_string (tmp);
-
- if (netdev_parent) {
- if (!strcmp (netdev_parent, serial_grandparent)) {
- /* We found it */
- tmp = libhal_device_get_property_string (ctx, netdevs[i], "net.interface", NULL);
- if (tmp) {
- netdev = g_strdup (tmp);
- libhal_free_string (tmp);
- }
- }
-
- libhal_free_string (netdev_parent);
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!(caps & MM_PLUGIN_BASE_PORT_CAP_GSM) && strcmp (subsys, "net"))
+ goto out;
+
+ if (!existing) {
+ modem = mm_modem_hso_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
}
}
+ } else {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
}
- cleanup:
- libhal_free_string_array (netdevs);
- libhal_free_string (serial_parent);
-
- return netdev;
-}
-
-static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
-{
- char *serial_device;
- char *net_device;
- char *driver;
- MMModem *modem;
-
- serial_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (serial_device != NULL, NULL);
-
- driver = get_driver_name (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
-
- net_device = get_netdev (hal_ctx, udi);
- g_return_val_if_fail (net_device != NULL, NULL);
-
- modem = MM_MODEM (mm_modem_hso_new (serial_device, net_device, driver));
-
- g_free (serial_device);
- g_free (net_device);
- g_free (driver);
-
+out:
+ g_free (devfile);
return modem;
}
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_hso_init (MMPluginHso *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_hso_class_init (MMPluginHsoClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
}
diff --git a/plugins/mm-plugin-hso.h b/plugins/mm-plugin-hso.h
index 2395837c..a3f4caf9 100644
--- a/plugins/mm-plugin-hso.h
+++ b/plugins/mm-plugin-hso.h
@@ -1,24 +1,39 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_PLUGIN_HSO_H
#define MM_PLUGIN_HSO_H
#include "mm-plugin.h"
+#include "mm-plugin-base.h"
#include "mm-generic-gsm.h"
-#define MM_TYPE_PLUGIN_HSO (mm_plugin_hso_get_type ())
-#define MM_PLUGIN_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HSO, MMPluginHso))
-#define MM_PLUGIN_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HSO, MMPluginHsoClass))
-#define MM_IS_PLUGIN_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HSO))
-#define MM_IS_PLUGIN_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HSO))
-#define MM_PLUGIN_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HSO, MMPluginHsoClass))
+#define MM_TYPE_PLUGIN_HSO (mm_plugin_hso_get_type ())
+#define MM_PLUGIN_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HSO, MMPluginHso))
+#define MM_PLUGIN_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HSO, MMPluginHsoClass))
+#define MM_IS_PLUGIN_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HSO))
+#define MM_IS_PLUGIN_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HSO))
+#define MM_PLUGIN_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HSO, MMPluginHsoClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginHso;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginHsoClass;
GType mm_plugin_hso_get_type (void);
diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c
index 206fa7b5..4ef8c578 100644
--- a/plugins/mm-plugin-huawei.c
+++ b/plugins/mm-plugin-huawei.c
@@ -1,14 +1,32 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <string.h>
#include <gmodule.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
#include "mm-plugin-huawei.h"
+#include "mm-generic-gsm.h"
+#include "mm-generic-cdma.h"
#include "mm-modem-huawei.h"
+#include "mm-serial-parsers.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginHuawei, mm_plugin_huawei, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginHuawei, mm_plugin_huawei, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
@@ -16,188 +34,287 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_HUAWEI, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_HUAWEI,
+ MM_PLUGIN_BASE_NAME, "Huawei",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
+#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
+
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- return "Huawei";
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ if (capabilities & CAP_CDMA)
+ return 10;
+ return 0;
}
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
+}
- devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
+#define TAG_SUPPORTS_INFO "huawei-supports-info"
- array = g_ptr_array_new ();
+typedef struct {
+ MMSerialPort *serial;
+ guint id;
+ gboolean secondary;
+} HuaweiSupportsInfo;
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
+static void
+huawei_supports_info_destroy (gpointer user_data)
+{
+ HuaweiSupportsInfo *info = user_data;
+
+ if (info->id)
+ g_source_remove (info->id);
+ if (info->serial)
+ g_object_unref (info->serial);
+ memset (info, 0, sizeof (HuaweiSupportsInfo));
+ g_free (info);
+}
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
- }
+static gboolean
+probe_secondary_supported (gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
- }
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
- g_strfreev (devices);
+ info->id = 0;
+ g_object_unref (info->serial);
+ info->serial = NULL;
- return supported;
+ /* Yay, supported, we got an unsolicited message */
+ info->secondary = TRUE;
+ mm_plugin_base_supports_task_complete (task, 10);
+ return FALSE;
}
-static int
-get_product (LibHalContext *hal_ctx, const char *udi)
+static void
+probe_secondary_handle_msg (MMSerialPort *port,
+ GMatchInfo *match_info,
+ gpointer user_data)
{
- char *parent_udi;
- int product = 0;
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
- parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- product = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.product_id", NULL);
- libhal_free_string (parent_udi);
- }
-
- return product;
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ g_source_remove (info->id);
+ info->id = g_idle_add (probe_secondary_supported, task);
}
static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+probe_secondary_timeout (gpointer user_data)
{
- char **capabilities;
- char **iter;
- gboolean supported = FALSE;
-
- capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter && !supported; iter++) {
- if (!strcmp (*iter, "GSM-07.07")) {
- char *parent_udi;
-
- parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- int vendor;
- int product;
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
- vendor = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.vendor_id", NULL);
- product = get_product (hal_ctx, udi);
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ info->id = 0;
+ g_object_unref (info->serial);
+ info->serial = NULL;
- if (vendor == 0x12d1 && (product == 0x1001 || product == 0x1003 || product == 0x1004))
- supported = TRUE;
-
- libhal_free_string (parent_udi);
- }
- }
- }
- g_strfreev (capabilities);
-
- return supported;
+ /* Not supported by this plugin */
+ mm_plugin_base_supports_task_complete (task, 0);
+ return FALSE;
}
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
+static void
+add_regex (MMSerialPort *port, const char *match, gpointer user_data)
{
- char *parent_udi;
- char *driver = NULL;
-
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
- }
+ GRegex *regex;
- return driver;
+ regex = g_regex_new (match, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (port, regex, probe_secondary_handle_msg, user_data, NULL);
+ g_regex_unref (regex);
}
-static char *
-find_second_port (LibHalContext *ctx, const char *parent)
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
{
- char **children;
- char *second_port = NULL;
- int num_children = 0;
- int i;
-
- if (!libhal_device_property_exists (ctx, parent, "usb.interface.number", NULL) ||
- libhal_device_get_property_int (ctx, parent, "usb.interface.number", NULL) != 1)
- return NULL;
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ const char *subsys, *name;
+ int usbif;
+ guint16 vendor = 0, product = 0;
+ guint32 existing_type = MM_MODEM_TYPE_UNKNOWN;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (vendor != 0x12d1)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ usbif = g_udev_device_get_property_as_int (port, "ID_USB_INTERFACE_NUM");
+ if (usbif < 0)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ /* The secondary ports don't necessarily respond correctly to probing, so
+ * we need to use the first port that does respond to probing to create the
+ * right type of mode (GSM or CDMA), and then re-check the other interfaces.
+ */
+ if (!existing && usbif != 0)
+ return MM_PLUGIN_SUPPORTS_PORT_DEFER;
+
+ /* CDMA devices don't have problems with the secondary ports, so after
+ * ensuring we have a device by probing the first port, probe the secondary
+ * ports on CDMA devices too.
+ */
+ if (existing)
+ g_object_get (G_OBJECT (existing), MM_MODEM_TYPE, &existing_type, NULL);
+
+ if (usbif == 0 || (existing_type == MM_MODEM_TYPE_CDMA)) {
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
- children = libhal_manager_find_device_string_match (ctx, "info.parent", parent, &num_children, NULL);
- for (i = 0; i < num_children && second_port == NULL; i++)
- second_port = libhal_device_get_property_string (ctx, children[i], "serial.device", NULL);
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ } else {
+ HuaweiSupportsInfo *info;
+ GError *error = NULL;
+
+ /* Listen for Huawei-specific unsolicited messages */
+ info = g_malloc0 (sizeof (HuaweiSupportsInfo));
+
+ info->serial = mm_serial_port_new (name, MM_PORT_TYPE_PRIMARY);
+ g_object_set (G_OBJECT (info->serial), MM_PORT_CARRIER_DETECT, FALSE, NULL);
+
+ mm_serial_port_set_response_parser (info->serial,
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
+
+ add_regex (info->serial, "\\r\\n\\^RSSI:(\\d+)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^BOOT:.+\\r\\n", task);
+
+ info->id = g_timeout_add (5000, probe_secondary_timeout, task);
+
+ g_object_set_data_full (G_OBJECT (task), TAG_SUPPORTS_INFO,
+ info, huawei_supports_info_destroy);
+
+ if (!mm_serial_port_open (info->serial, &error)) {
+ g_warning ("%s: (Huawei) %s: couldn't open serial port: (%d) %s",
+ __func__, name,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ huawei_supports_info_destroy (info);
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
- libhal_free_string_array (children);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
- return second_port;
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
-static char *
-get_monitor_device (LibHalContext *ctx, const char *udi)
+static MMModem *
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *parent;
- char *grand_parent;
- char **uncles;
- char *monitor_device = NULL;
- int num_uncles = 0;
- int i;
-
- parent = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- grand_parent = libhal_device_get_property_string (ctx, parent, "info.parent", NULL);
-
- /* Find "uncles" */
- uncles = libhal_manager_find_device_string_match (ctx, "info.parent", grand_parent, &num_uncles, NULL);
- for (i = 0; i < num_uncles && monitor_device == NULL; i++) {
- const char *uncle = uncles[i];
-
- /* Ignore "dad" */
- if (strcmp (uncle, parent))
- monitor_device = find_second_port (ctx, uncle);
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *devfile, *sysfs_path;
+ guint32 caps;
+ guint16 product = 0;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ devfile = g_udev_device_get_device_file (port);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ return NULL;
}
- libhal_free_string_array (uncles);
- libhal_free_string (parent);
- libhal_free_string (grand_parent);
-
- return monitor_device;
-}
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
-static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
-{
- char *data_device;
- char *monitor_device;
- char *driver;
- MMModem *modem;
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
- data_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (data_device != NULL, NULL);
+ if (!mm_plugin_base_get_device_ids (base, subsys, name, NULL, &product)) {
+ g_set_error (error, 0, 0, "Could not get modem product ID.");
+ return NULL;
+ }
- driver = get_driver_name (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ if (product == 0x1001) {
+ /* This modem is handled by generic GSM driver */
+ modem = mm_generic_gsm_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ } else {
+ modem = mm_modem_huawei_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
+ } else if (caps & CAP_CDMA) {
+ modem = mm_generic_cdma_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
- if (get_product (hal_ctx, udi) == 0x1001) {
- /* This modem is handled by generic GSM device */
- modem = mm_generic_gsm_new (data_device, driver);
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
} else {
- monitor_device = get_monitor_device (hal_ctx, udi);
- modem = mm_modem_huawei_new (data_device, monitor_device, driver);
- libhal_free_string (monitor_device);
- }
+ HuaweiSupportsInfo *info;
+ gboolean huawei_is_secondary = FALSE;
- libhal_free_string (data_device);
- libhal_free_string (driver);
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ if (info && (product != 0x1001))
+ huawei_is_secondary = info->secondary;
+
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, GUINT_TO_POINTER (huawei_is_secondary), error))
+ return NULL;
+ }
return modem;
}
@@ -205,21 +322,16 @@ create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_huawei_init (MMPluginHuawei *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_huawei_class_init (MMPluginHuaweiClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
}
diff --git a/plugins/mm-plugin-huawei.h b/plugins/mm-plugin-huawei.h
index e37a3a7a..de9294c4 100644
--- a/plugins/mm-plugin-huawei.h
+++ b/plugins/mm-plugin-huawei.h
@@ -1,24 +1,38 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_PLUGIN_HUAWEI_H
#define MM_PLUGIN_HUAWEI_H
#include "mm-plugin.h"
-#include "mm-generic-gsm.h"
+#include "mm-plugin-base.h"
-#define MM_TYPE_PLUGIN_HUAWEI (mm_plugin_huawei_get_type ())
-#define MM_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuawei))
-#define MM_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass))
-#define MM_IS_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HUAWEI))
-#define MM_IS_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HUAWEI))
-#define MM_PLUGIN_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass))
+#define MM_TYPE_PLUGIN_HUAWEI (mm_plugin_huawei_get_type ())
+#define MM_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuawei))
+#define MM_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass))
+#define MM_IS_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HUAWEI))
+#define MM_IS_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HUAWEI))
+#define MM_PLUGIN_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginHuawei;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginHuaweiClass;
GType mm_plugin_huawei_get_type (void);
diff --git a/plugins/mm-plugin-mbm.c b/plugins/mm-plugin-mbm.c
index c4b58e55..2af7eed7 100644
--- a/plugins/mm-plugin-mbm.c
+++ b/plugins/mm-plugin-mbm.c
@@ -22,13 +22,14 @@
#include <string.h>
#include <gmodule.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
#include "mm-plugin-mbm.h"
#include "mm-modem-mbm.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginMbm, mm_plugin_mbm, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginMbm, mm_plugin_mbm, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
@@ -36,196 +37,122 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_MBM, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_MBM,
+ MM_PLUGIN_BASE_NAME, "Ericsson MBM",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- return "MBM";
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ return 0;
}
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
-
- devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
-
- array = g_ptr_array_new ();
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
+}
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
+{
+ GUdevDevice *port, *physdev;
+ guint32 cached = 0, level;
+ const char *driver, *subsys;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+ subsys = g_udev_device_get_subsystem (port);
+ g_assert (subsys);
+
+ if (strcmp (subsys, "tty") && strcmp (subsys, "net"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (!driver)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ if (!g_udev_device_get_property_as_boolean (physdev, "ID_MM_ERICSSON_MBM"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (!strcmp (subsys, "net")) {
+ mm_plugin_base_supports_task_complete (task, 10);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
}
-
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- g_strfreev (devices);
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
- return supported;
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
-static char *
-get_netdev (LibHalContext *ctx, const char *udi)
+static MMModem *
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *serial_parent, *serial_parent_parent, *netdev = NULL;
- char **netdevs;
- int num, i;
-
- /* Get the origin udi, which is parent of our parent */
- serial_parent = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (!serial_parent)
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *sysfs_path;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
return NULL;
- /* Just attach to first cdc-acm interface */
- if (strncmp (serial_parent + strlen (serial_parent) - 4, "_if1", 4))
- return NULL;
- serial_parent_parent = libhal_device_get_property_string (ctx, serial_parent, "info.parent", NULL);
- if (!serial_parent_parent)
- return NULL;
-
- /* Look for the originating device's netdev */
- netdevs = libhal_find_device_by_capability (ctx, "net", &num, NULL);
- for (i = 0; netdevs && !netdev && (i < num); i++) {
- char *netdev_parent, *netdev_parent_parent, *tmp;
-
- /* Get the origin udi, which also is parent of our parent */
- netdev_parent = libhal_device_get_property_string (ctx, netdevs[i], "info.parent", NULL);
- if (!netdev_parent)
- continue;
- netdev_parent_parent = libhal_device_get_property_string (ctx, netdev_parent, "info.parent", NULL);
- if (!netdev_parent_parent)
- continue;
-
- if (!strcmp (netdev_parent_parent, serial_parent_parent)) {
- /* We found it */
- tmp = libhal_device_get_property_string (ctx, netdevs[i], "net.interface", NULL);
- if (tmp) {
- netdev = g_strdup (tmp);
- libhal_free_string (tmp);
- }
- }
-
- libhal_free_string (netdev_parent);
- libhal_free_string (netdev_parent_parent);
}
- libhal_free_string_array (netdevs);
- libhal_free_string (serial_parent);
- libhal_free_string (serial_parent_parent);
- return netdev;
-}
-
-static char *
-get_driver (LibHalContext *ctx, const char *udi)
-{
- char *serial_parent, *serial_parent_parent, *driver = NULL;
- char **netdevs;
- int num, i;
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
- /* Get the origin udi, which is parent of our parent */
- serial_parent = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (!serial_parent)
- return NULL;
- serial_parent_parent = libhal_device_get_property_string (ctx, serial_parent, "info.parent", NULL);
- if (!serial_parent_parent)
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!(caps & MM_PLUGIN_BASE_PORT_CAP_GSM) && strcmp (subsys, "net"))
return NULL;
- /* Look for the originating device's netdev */
- netdevs = libhal_find_device_by_capability (ctx, "net", &num, NULL);
- for (i = 0; netdevs && !driver && (i < num); i++) {
- char *netdev_parent, *netdev_parent_parent, *tmp;
-
- /* Get the origin udi, which also is parent of our parent */
- netdev_parent = libhal_device_get_property_string (ctx, netdevs[i], "info.parent", NULL);
- if (!netdev_parent)
- continue;
- netdev_parent_parent = libhal_device_get_property_string (ctx, netdev_parent, "info.parent", NULL);
- if (!netdev_parent_parent)
- continue;
-
- if (!strcmp (netdev_parent_parent, serial_parent_parent)) {
- /* We found it */
- tmp = libhal_device_get_property_string (ctx,
- netdev_parent, "info.linux.driver", NULL);
- if (tmp) {
- driver = g_strdup (tmp);
- libhal_free_string (tmp);
+ if (!existing) {
+ modem = mm_modem_mbm_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
}
}
-
- libhal_free_string (netdev_parent);
- libhal_free_string (netdev_parent_parent);
+ } else {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
}
- libhal_free_string_array (netdevs);
- libhal_free_string (serial_parent);
- libhal_free_string (serial_parent_parent);
-
- return driver;
-}
-
-static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
-{
- char *driver_name;
- gboolean supported = FALSE;
-
- driver_name = get_driver (hal_ctx, udi);
- if (driver_name && (!strcmp (driver_name, "cdc_ether") || !strcmp (driver_name, "mbm"))) {
- char **capabilities;
- char **iter;
-
- capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter && !supported; iter++) {
- if (!strcmp (*iter, "GSM-07.07") || !strcmp (*iter, "GSM-07.05")) {
- supported = TRUE;
- break;
- }
- }
-
- libhal_free_string_array (capabilities);
- }
-
- libhal_free_string (driver_name);
-
- return supported;
-}
-
-static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
-{
- char *serial_device;
- char *net_device;
- char *driver;
- MMModem *modem;
-
- serial_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (serial_device != NULL, NULL);
-
- net_device = get_netdev (hal_ctx, udi);
- g_return_val_if_fail (net_device != NULL, NULL);
-
- driver = get_driver (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
-
- modem = MM_MODEM (mm_modem_mbm_new (serial_device, net_device, driver));
-
- g_free (serial_device);
- g_free (net_device);
return modem;
}
@@ -233,21 +160,16 @@ create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_mbm_init (MMPluginMbm *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_mbm_class_init (MMPluginMbmClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
}
diff --git a/plugins/mm-plugin-mbm.h b/plugins/mm-plugin-mbm.h
index e0d2c56a..c0e73b56 100644
--- a/plugins/mm-plugin-mbm.h
+++ b/plugins/mm-plugin-mbm.h
@@ -23,22 +23,22 @@
#ifndef MM_PLUGIN_MBM_H
#define MM_PLUGIN_MBM_H
-#include "mm-plugin.h"
+#include "mm-plugin-base.h"
#include "mm-generic-gsm.h"
-#define MM_TYPE_PLUGIN_MBM (mm_plugin_mbm_get_type ())
-#define MM_PLUGIN_MBM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_MBM, MMPluginMbm))
+#define MM_TYPE_PLUGIN_MBM (mm_plugin_mbm_get_type ())
+#define MM_PLUGIN_MBM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_MBM, MMPluginMbm))
#define MM_PLUGIN_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_MBM, MMPluginMbmClass))
#define MM_IS_PLUGIN_MBM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_MBM))
#define MM_IS_PLUGIN_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_MBM))
#define MM_PLUGIN_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_MBM, MMPluginMbmClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginMbm;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginMbmClass;
GType mm_plugin_mbm_get_type (void);
diff --git a/plugins/mm-plugin-moto-c.c b/plugins/mm-plugin-moto-c.c
new file mode 100644
index 00000000..3e253613
--- /dev/null
+++ b/plugins/mm-plugin-moto-c.c
@@ -0,0 +1,160 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <gmodule.h>
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
+#include "mm-plugin-moto-c.h"
+#include "mm-modem-moto-c-gsm.h"
+
+G_DEFINE_TYPE (MMPluginMotoC, mm_plugin_moto_c, MM_TYPE_PLUGIN_BASE)
+
+int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
+int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
+
+G_MODULE_EXPORT MMPlugin *
+mm_plugin_create (void)
+{
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_MOTO_C,
+ MM_PLUGIN_BASE_NAME, "MotoC",
+ NULL));
+}
+
+/*****************************************************************************/
+
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
+{
+ guint32 level = 0;
+
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ level = 10;
+
+ mm_plugin_base_supports_task_complete (task, level);
+}
+
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
+{
+ GUdevDevice *port;
+ const char *tmp;
+ guint32 cached = 0;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ tmp = g_udev_device_get_property (port, "ID_BUS");
+ if (!tmp || strcmp (tmp, "usb"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ tmp = g_udev_device_get_property (port, "ID_VENDOR_ID");
+ if (!tmp || strcmp (tmp, "22b8"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ tmp = g_udev_device_get_property (port, "ID_MODEL_ID");
+ if (!tmp || strcmp (tmp, "3802"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ if (cached & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ mm_plugin_base_supports_task_complete (task, 10);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
+
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+}
+
+static MMModem *
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
+{
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *devfile, *sysfs_path;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ devfile = g_udev_device_get_device_file (port);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ return NULL;
+ }
+
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ if (!existing) {
+ modem = mm_modem_moto_c_gsm_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
+ }
+
+ return modem;
+}
+
+/*****************************************************************************/
+
+static void
+mm_plugin_moto_c_init (MMPluginMotoC *self)
+{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
+}
+
+static void
+mm_plugin_moto_c_class_init (MMPluginMotoCClass *klass)
+{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
+}
diff --git a/plugins/mm-plugin-moto-c.h b/plugins/mm-plugin-moto-c.h
new file mode 100644
index 00000000..8583607b
--- /dev/null
+++ b/plugins/mm-plugin-moto-c.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_PLUGIN_MOTO_C_H
+#define MM_PLUGIN_MOTO_C_H
+
+#include "mm-plugin.h"
+#include "mm-plugin-base.h"
+#include "mm-generic-gsm.h"
+
+#define MM_TYPE_PLUGIN_MOTO_C (mm_plugin_moto_c_get_type ())
+#define MM_PLUGIN_MOTO_C(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_MOTO_C, MMPluginMotoC))
+#define MM_PLUGIN_MOTO_C_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_MOTO_C, MMPluginMotoCClass))
+#define MM_IS_PLUGIN_MOTO_C(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_MOTO_C))
+#define MM_IS_PLUGIN_MOTO_C_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_MOTO_C))
+#define MM_PLUGIN_MOTO_C_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_MOTO_C, MMPluginMotoCClass))
+
+typedef struct {
+ MMPluginBase parent;
+} MMPluginMotoC;
+
+typedef struct {
+ MMPluginBaseClass parent;
+} MMPluginMotoCClass;
+
+GType mm_plugin_moto_c_get_type (void);
+
+G_MODULE_EXPORT MMPlugin *mm_plugin_create (void);
+
+#endif /* MM_PLUGIN_MOTO_C_H */
diff --git a/plugins/mm-plugin-nokia.c b/plugins/mm-plugin-nokia.c
index 4d1dc955..06232209 100644
--- a/plugins/mm-plugin-nokia.c
+++ b/plugins/mm-plugin-nokia.c
@@ -1,14 +1,26 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <string.h>
#include <gmodule.h>
#include "mm-plugin-nokia.h"
#include "mm-modem-nokia.h"
+#include "mm-generic-cdma.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginNokia, mm_plugin_nokia, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginNokia, mm_plugin_nokia, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
@@ -16,111 +28,133 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_NOKIA, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_NOKIA,
+ MM_PLUGIN_BASE_NAME, "Nokia",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
+#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
+
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- return "Nokia";
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ if (capabilities & CAP_CDMA)
+ return 10;
+ return 0;
}
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
-
- devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
-
- array = g_ptr_array_new ();
-
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
-
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
- }
-
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
- }
-
- g_strfreev (devices);
-
- return supported;
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
-static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
{
- char **capabilities;
- char **iter;
- gboolean supported = FALSE;
-
- capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter && !supported; iter++) {
- if (!strcmp (*iter, "GSM-07.07")) {
- char *parent_udi;
-
- parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- int vendor;
-
- vendor = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.vendor_id", NULL);
- if (vendor == 0x0421)
- supported = TRUE;
-
- libhal_free_string (parent_udi);
- }
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ const char *subsys, *name;
+ guint16 vendor = 0;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (vendor != 0x0421)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
}
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- g_strfreev (capabilities);
- return supported;
-}
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
-{
- char *parent_udi;
- char *driver = NULL;
-
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
- }
-
- return driver;
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *data_device;
- char *driver;
- MMModem *modem;
-
- data_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (data_device != NULL, NULL);
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *devfile, *sysfs_path;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ devfile = g_udev_device_get_device_file (port);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ return NULL;
+ }
- driver = get_driver_name (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
- modem = MM_MODEM (mm_modem_nokia_new (data_device, driver));
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ modem = mm_modem_nokia_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ } else if (caps & CAP_CDMA) {
+ modem = mm_generic_cdma_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
- libhal_free_string (data_device);
- libhal_free_string (driver);
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ if (caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
+ }
+ }
return modem;
}
@@ -128,21 +162,16 @@ create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_nokia_init (MMPluginNokia *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_nokia_class_init (MMPluginNokiaClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
}
diff --git a/plugins/mm-plugin-nokia.h b/plugins/mm-plugin-nokia.h
index 014e3022..fdc0f417 100644
--- a/plugins/mm-plugin-nokia.h
+++ b/plugins/mm-plugin-nokia.h
@@ -1,10 +1,23 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_PLUGIN_NOKIA_H
#define MM_PLUGIN_NOKIA_H
-#include "mm-plugin.h"
-#include "mm-generic-gsm.h"
+#include "mm-plugin-base.h"
#define MM_TYPE_PLUGIN_NOKIA (mm_plugin_nokia_get_type ())
#define MM_PLUGIN_NOKIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_NOKIA, MMPluginNokia))
@@ -14,11 +27,11 @@
#define MM_PLUGIN_NOKIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_NOKIA, MMPluginNokiaClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginNokia;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginNokiaClass;
GType mm_plugin_nokia_get_type (void);
diff --git a/plugins/mm-plugin-novatel.c b/plugins/mm-plugin-novatel.c
index 0957c7d5..33ab393b 100644
--- a/plugins/mm-plugin-novatel.c
+++ b/plugins/mm-plugin-novatel.c
@@ -1,15 +1,26 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <string.h>
#include <gmodule.h>
#include "mm-plugin-novatel.h"
-#include "mm-modem-novatel-cdma.h"
#include "mm-modem-novatel-gsm.h"
+#include "mm-generic-cdma.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginNovatel, mm_plugin_novatel, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginNovatel, mm_plugin_novatel, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
@@ -17,136 +28,137 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_NOVATEL, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_NOVATEL,
+ MM_PLUGIN_BASE_NAME, "Novatel",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
-{
- return "Novatel";
-}
+#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
-
- devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
-
- array = g_ptr_array_new ();
-
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
-
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
- }
-
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
- }
-
- g_strfreev (devices);
-
- return supported;
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ if (capabilities & CAP_CDMA)
+ return 10;
+ return 0;
}
static void
-is_novatel_modem (LibHalContext *hal_ctx,
- const char *udi,
- gboolean *is_novatel_gsm,
- gboolean *is_novatel_cdma)
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **capabilities;
- char **iter;
-
- *is_novatel_gsm = *is_novatel_cdma = FALSE;
-
- capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter && !*is_novatel_gsm && !*is_novatel_cdma; iter++) {
- char *parent_udi;
-
- parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- int vendor;
-
- vendor = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.vendor_id", NULL);
- if (vendor == 0x1410) {
- if (!strcmp (*iter, "GSM-07.07")) {
- *is_novatel_gsm = TRUE;
- } else if (!strcmp (*iter, "IS-707-A")) {
- *is_novatel_cdma = TRUE;
- }
- }
-
- libhal_free_string (parent_udi);
- }
- }
-
- g_strfreev (capabilities);
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
-static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
{
- gboolean is_novatel_gsm = FALSE;
- gboolean is_novatel_cdma = FALSE;
-
- is_novatel_modem (hal_ctx, udi, &is_novatel_gsm, &is_novatel_cdma);
-
- return is_novatel_gsm || is_novatel_cdma;
-}
-
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
-{
- char *parent_udi;
- char *driver = NULL;
-
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ const char *subsys, *name, *driver;
+ guint16 vendor = 0;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (!driver || (strcmp (driver, "option1") && strcmp (driver, "option")))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (vendor != 0x1410 && vendor != 0x413c)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- return driver;
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *data_device;
- char *driver;
- MMModem *modem;
- gboolean is_novatel_gsm = FALSE;
- gboolean is_novatel_cdma = FALSE;
-
- is_novatel_modem (hal_ctx, udi, &is_novatel_gsm, &is_novatel_cdma);
- g_return_val_if_fail (!is_novatel_gsm && !is_novatel_cdma, NULL);
-
- data_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (data_device != NULL, NULL);
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *devfile, *sysfs_path;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ devfile = g_udev_device_get_device_file (port);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ return NULL;
+ }
- driver = get_driver_name (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
- if (is_novatel_gsm)
- modem = MM_MODEM (mm_modem_novatel_gsm_new (data_device, driver));
- else
- modem = MM_MODEM (mm_modem_novatel_cdma_new (data_device, driver));
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ modem = mm_modem_novatel_gsm_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ } else if (caps & CAP_CDMA) {
+ modem = mm_generic_cdma_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
- libhal_free_string (data_device);
- libhal_free_string (driver);
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ if (caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
+ }
+ }
return modem;
}
@@ -154,21 +166,16 @@ create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_novatel_init (MMPluginNovatel *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_novatel_class_init (MMPluginNovatelClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
}
diff --git a/plugins/mm-plugin-novatel.h b/plugins/mm-plugin-novatel.h
index fbbf9735..450bbddd 100644
--- a/plugins/mm-plugin-novatel.h
+++ b/plugins/mm-plugin-novatel.h
@@ -1,9 +1,23 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_PLUGIN_NOVATEL_H
#define MM_PLUGIN_NOVATEL_H
-#include "mm-plugin.h"
+#include "mm-plugin-base.h"
#include "mm-generic-gsm.h"
#define MM_TYPE_PLUGIN_NOVATEL (mm_plugin_novatel_get_type ())
@@ -14,11 +28,11 @@
#define MM_PLUGIN_NOVATEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_NOVATEL, MMPluginNovatelClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginNovatel;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginNovatelClass;
GType mm_plugin_novatel_get_type (void);
diff --git a/plugins/mm-plugin-option.c b/plugins/mm-plugin-option.c
index 1a231f40..6f4aaa97 100644
--- a/plugins/mm-plugin-option.c
+++ b/plugins/mm-plugin-option.c
@@ -1,14 +1,25 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <string.h>
#include <gmodule.h>
#include "mm-plugin-option.h"
#include "mm-modem-option.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginOption, mm_plugin_option, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginOption, mm_plugin_option, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
@@ -16,117 +27,126 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_OPTION, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_OPTION,
+ MM_PLUGIN_BASE_NAME, "Option",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- return "Option";
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ return 0;
}
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
-
- devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
-
- array = g_ptr_array_new ();
-
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
-
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
- }
-
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
- }
-
- g_strfreev (devices);
-
- return supported;
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
-static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
{
- char **capabilities;
- char **iter;
- gboolean supported = FALSE;
-
- capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter && !supported; iter++) {
- if (!strcmp (*iter, "GSM-07.07")) {
- char *parent_udi;
-
- parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- int vendor;
-
- vendor = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.vendor_id", NULL);
- if (vendor == 0x0af0) {
- char *driver;
-
- driver = libhal_device_get_property_string (hal_ctx, parent_udi, "info.linux.driver", NULL);
- if (driver && !strcmp (driver, "option"))
- supported = TRUE;
- libhal_free_string (driver);
- }
-
- libhal_free_string (parent_udi);
- }
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ const char *driver, *subsys, *name;
+ guint16 vendor = 0;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (!driver || (strcmp (driver, "option1") && strcmp (driver, "option")))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (vendor != 0x0af0)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
}
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- g_strfreev (capabilities);
- return supported;
-}
-
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
-{
- char *parent_udi;
- char *driver = NULL;
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
- }
-
- return driver;
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *data_device;
- char *driver;
- MMModem *modem;
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *devfile, *sysfs_path;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ devfile = g_udev_device_get_device_file (port);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ return NULL;
+ }
- data_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (data_device != NULL, NULL);
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
- driver = get_driver_name (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
- modem = MM_MODEM (mm_modem_option_new (data_device, driver));
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ modem = mm_modem_option_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
- libhal_free_string (data_device);
- libhal_free_string (driver);
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
+ }
+ }
return modem;
}
@@ -134,21 +154,16 @@ create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_option_init (MMPluginOption *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_option_class_init (MMPluginOptionClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
}
diff --git a/plugins/mm-plugin-option.h b/plugins/mm-plugin-option.h
index 7ac7e8a5..dfcff749 100644
--- a/plugins/mm-plugin-option.h
+++ b/plugins/mm-plugin-option.h
@@ -1,9 +1,23 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_PLUGIN_OPTION_H
#define MM_PLUGIN_OPTION_H
-#include "mm-plugin.h"
+#include "mm-plugin-base.h"
#include "mm-generic-gsm.h"
#define MM_TYPE_PLUGIN_OPTION (mm_plugin_option_get_type ())
@@ -14,11 +28,11 @@
#define MM_PLUGIN_OPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_OPTION, MMPluginOptionClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginOption;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginOptionClass;
GType mm_plugin_option_get_type (void);
diff --git a/plugins/mm-plugin-sierra.c b/plugins/mm-plugin-sierra.c
index 7185c4dd..e3d1bafb 100644
--- a/plugins/mm-plugin-sierra.c
+++ b/plugins/mm-plugin-sierra.c
@@ -1,14 +1,26 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <string.h>
#include <gmodule.h>
#include "mm-plugin-sierra.h"
#include "mm-modem-sierra.h"
+#include "mm-generic-cdma.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginSierra, mm_plugin_sierra, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginSierra, mm_plugin_sierra, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
@@ -16,119 +28,156 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_SIERRA, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_SIERRA,
+ MM_PLUGIN_BASE_NAME, "Sierra",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
+#define TAG_SIERRA_SECONDARY_PORT "sierra-secondary-port"
+
+#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
+
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- return "Sierra";
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ if (capabilities & CAP_CDMA)
+ return 10;
+ return 0;
}
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static void
+handle_probe_response (MMPluginBase *self,
+ MMPluginBaseSupportsTask *task,
+ const char *cmd,
+ const char *response,
+ const GError *error)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
-
- devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
-
- array = g_ptr_array_new ();
-
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
-
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
- }
-
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
+ if (error || !response || strcmp (cmd, "I")) {
+ MM_PLUGIN_BASE_CLASS (mm_plugin_sierra_parent_class)->handle_probe_response (self, task, cmd, response, error);
+ return;
}
- g_strfreev (devices);
+ if (strstr (response, "APP1") || strstr (response, "APP2") || strstr (response, "APP3")) {
+ g_object_set_data (G_OBJECT (task), TAG_SIERRA_SECONDARY_PORT, GUINT_TO_POINTER (TRUE));
+ mm_plugin_base_supports_task_complete (task, 10);
+ return;
+ }
- return supported;
+ /* Not an app port, let the superclass handle the response */
+ MM_PLUGIN_BASE_CLASS (mm_plugin_sierra_parent_class)->handle_probe_response (self, task, cmd, response, error);
}
-static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **capabilities;
- char **iter;
- gboolean supported = FALSE;
-
- capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter && !supported; iter++) {
- if (!strcmp (*iter, "GSM-07.07")) {
- char *parent_udi;
-
- parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- int vendor;
-
- vendor = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.vendor_id", NULL);
- if (vendor == 0x1199)
- supported = TRUE;
-
- if (vendor == 0x03f0) {
- int product;
-
- product = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.product_id", NULL);
- if (product == 0x1e1d)
- supported = TRUE;
- }
-
- libhal_free_string (parent_udi);
- }
- }
- }
- g_strfreev (capabilities);
-
- return supported;
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
{
- char *parent_udi;
- char *driver = NULL;
-
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ const char *driver;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (!driver || strcmp (driver, "sierra"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- return driver;
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *data_device;
- char *driver;
- MMModem *modem;
-
- data_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (data_device != NULL, NULL);
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *devfile, *sysfs_path;
+ guint32 caps;
+ gpointer gsm_data = NULL;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ devfile = g_udev_device_get_device_file (port);
+ if (!devfile) {
+ g_set_error (error, 0, 0, "Could not get port's sysfs file.");
+ return NULL;
+ }
- driver = get_driver_name (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
- modem = MM_MODEM (mm_modem_sierra_new (data_device, driver));
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ /* Is it a GSM secondary port? */
+ if (g_object_get_data (G_OBJECT (task), TAG_SIERRA_SECONDARY_PORT))
+ gsm_data = GUINT_TO_POINTER (TRUE);
+
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if ((caps & MM_PLUGIN_BASE_PORT_CAP_GSM) || gsm_data) {
+ modem = mm_modem_sierra_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ } else if (caps & CAP_CDMA) {
+ modem = mm_generic_cdma_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
- libhal_free_string (data_device);
- libhal_free_string (driver);
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, gsm_data, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ if ((caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) || gsm_data) {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, gsm_data, error))
+ return NULL;
+ }
+ }
return modem;
}
@@ -136,21 +185,17 @@ create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_sierra_init (MMPluginSierra *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_sierra_class_init (MMPluginSierraClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
+ pb_class->handle_probe_response = handle_probe_response;
}
diff --git a/plugins/mm-plugin-sierra.h b/plugins/mm-plugin-sierra.h
index b2473acb..01fffc4c 100644
--- a/plugins/mm-plugin-sierra.h
+++ b/plugins/mm-plugin-sierra.h
@@ -1,9 +1,23 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_PLUGIN_SIERRA_H
#define MM_PLUGIN_SIERRA_H
-#include "mm-plugin.h"
+#include "mm-plugin-base.h"
#include "mm-generic-gsm.h"
#define MM_TYPE_PLUGIN_SIERRA (mm_plugin_sierra_get_type ())
@@ -14,11 +28,11 @@
#define MM_PLUGIN_SIERRA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_SIERRA, MMPluginSierraClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginSierra;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginSierraClass;
GType mm_plugin_sierra_get_type (void);
diff --git a/plugins/mm-plugin-zte.c b/plugins/mm-plugin-zte.c
index 29e90ab9..e830823f 100644
--- a/plugins/mm-plugin-zte.c
+++ b/plugins/mm-plugin-zte.c
@@ -1,14 +1,26 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <string.h>
#include <gmodule.h>
#include "mm-plugin-zte.h"
#include "mm-modem-zte.h"
+#include "mm-generic-cdma.h"
-static void plugin_init (MMPlugin *plugin_class);
-
-G_DEFINE_TYPE_EXTENDED (MMPluginZte, mm_plugin_zte, G_TYPE_OBJECT,
- 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+G_DEFINE_TYPE (MMPluginZte, mm_plugin_zte, MM_TYPE_PLUGIN_BASE)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
@@ -16,111 +28,127 @@ int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_ZTE, NULL));
+ return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_ZTE,
+ MM_PLUGIN_BASE_NAME, "ZTE",
+ NULL));
}
/*****************************************************************************/
-static const char *
-get_name (MMPlugin *plugin)
+#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
+
+static guint32
+get_level_for_capabilities (guint32 capabilities)
{
- return "ZTE";
+ if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM)
+ return 10;
+ if (capabilities & CAP_CDMA)
+ return 10;
+ return 0;
}
-static char **
-list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
+static void
+probe_result (MMPluginBase *base,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities,
+ gpointer user_data)
{
- char **supported = NULL;
- char **devices;
- int num_devices;
- int i;
-
- devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
- if (devices) {
- GPtrArray *array;
-
- array = g_ptr_array_new ();
-
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
-
- if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
- g_ptr_array_add (array, g_strdup (udi));
- }
-
- if (array->len > 0) {
- g_ptr_array_add (array, NULL);
- supported = (char **) g_ptr_array_free (array, FALSE);
- } else
- g_ptr_array_free (array, TRUE);
- }
-
- g_strfreev (devices);
-
- return supported;
+ mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
-static gboolean
-supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+static MMPluginSupportsResult
+supports_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task)
{
- char **capabilities;
- char **iter;
- gboolean supported = FALSE;
-
- capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter && !supported; iter++) {
- if (!strcmp (*iter, "GSM-07.07")) {
- char *parent_udi;
-
- parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- int vendor;
-
- vendor = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.vendor_id", NULL);
- if (vendor == 0x19d2)
- supported = TRUE;
-
- libhal_free_string (parent_udi);
- }
+ GUdevDevice *port;
+ guint32 cached = 0, level;
+ guint16 vendor = 0;
+ const char *subsys, *name;
+
+ /* Can't do anything with non-serial ports */
+ port = mm_plugin_base_supports_task_get_port (task);
+ if (strcmp (g_udev_device_get_subsystem (port), "tty"))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (vendor != 0x19d2)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
}
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- g_strfreev (capabilities);
- return supported;
-}
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, NULL))
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
-{
- char *parent_udi;
- char *driver = NULL;
-
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
- }
-
- return driver;
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
static MMModem *
-create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
+grab_port (MMPluginBase *base,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
{
- char *data_device;
- char *driver;
- MMModem *modem;
-
- data_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (data_device != NULL, NULL);
-
- driver = get_driver_name (hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
+ GUdevDevice *port = NULL, *physdev = NULL;
+ MMModem *modem = NULL;
+ const char *name, *subsys, *sysfs_path;
+ guint32 caps;
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+
+ physdev = mm_plugin_base_supports_task_get_physdev (task);
+ g_assert (physdev);
+ sysfs_path = g_udev_device_get_sysfs_path (physdev);
+ if (!sysfs_path) {
+ g_set_error (error, 0, 0, "Could not get port's physical device sysfs path.");
+ return NULL;
+ }
- modem = MM_MODEM (mm_modem_zte_new (data_device, driver));
+ subsys = g_udev_device_get_subsystem (port);
+ name = g_udev_device_get_name (port);
+
+ caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
+ if (!existing) {
+ if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
+ modem = mm_modem_zte_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ } else if (caps & CAP_CDMA) {
+ modem = mm_generic_cdma_new (sysfs_path,
+ mm_plugin_base_supports_task_get_driver (task),
+ mm_plugin_get_name (MM_PLUGIN (base)));
+ }
- libhal_free_string (data_device);
- libhal_free_string (driver);
+ if (modem) {
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) {
+ g_object_unref (modem);
+ return NULL;
+ }
+ }
+ } else {
+ if (caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) {
+ modem = existing;
+ if (!mm_modem_grab_port (modem, subsys, name, NULL, error))
+ return NULL;
+ }
+ }
return modem;
}
@@ -128,21 +156,16 @@ create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
/*****************************************************************************/
static void
-plugin_init (MMPlugin *plugin_class)
-{
- /* interface implementation */
- plugin_class->get_name = get_name;
- plugin_class->list_supported_udis = list_supported_udis;
- plugin_class->supports_udi = supports_udi;
- plugin_class->create_modem = create_modem;
-}
-
-static void
mm_plugin_zte_init (MMPluginZte *self)
{
+ g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL);
}
static void
mm_plugin_zte_class_init (MMPluginZteClass *klass)
{
+ MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass);
+
+ pb_class->supports_port = supports_port;
+ pb_class->grab_port = grab_port;
}
diff --git a/plugins/mm-plugin-zte.h b/plugins/mm-plugin-zte.h
index 9fe5b438..7a4d4c9a 100644
--- a/plugins/mm-plugin-zte.h
+++ b/plugins/mm-plugin-zte.h
@@ -1,9 +1,23 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#ifndef MM_PLUGIN_ZTE_H
#define MM_PLUGIN_ZTE_H
-#include "mm-plugin.h"
+#include "mm-plugin-base.h"
#define MM_TYPE_PLUGIN_ZTE (mm_plugin_zte_get_type ())
#define MM_PLUGIN_ZTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_ZTE, MMPluginZte))
@@ -13,11 +27,11 @@
#define MM_PLUGIN_ZTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_ZTE, MMPluginZteClass))
typedef struct {
- GObject parent;
+ MMPluginBase parent;
} MMPluginZte;
typedef struct {
- GObjectClass parent;
+ MMPluginBaseClass parent;
} MMPluginZteClass;
GType mm_plugin_zte_get_type (void);
diff --git a/src/Makefile.am b/src/Makefile.am
index d6d4e73f..b8374fef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,27 +2,37 @@ sbin_PROGRAMS = modem-manager
modem_manager_CPPFLAGS = \
$(MM_CFLAGS) \
+ $(GUDEV_CFLAGS) \
-I${top_builddir}/marshallers \
-DPLUGINDIR=\"$(pkglibdir)\"
modem_manager_LDADD = \
$(MM_LIBS) \
+ $(GUDEV_LIBS) \
$(top_builddir)/marshallers/libmarshallers.la
modem_manager_SOURCES = \
main.c \
mm-callback-info.c \
mm-callback-info.h \
- mm-generic-cdma.c \
- mm-generic-cdma.h \
- mm-generic-gsm.c \
- mm-generic-gsm.h \
mm-errors.c \
mm-errors.h \
mm-manager.c \
mm-manager.h \
mm-modem.c \
mm-modem.h \
+ mm-port.c \
+ mm-port.h \
+ mm-modem-base.c \
+ mm-modem-base.h \
+ mm-serial-port.c \
+ mm-serial-port.h \
+ mm-serial-parsers.c \
+ mm-serial-parsers.h \
+ mm-generic-cdma.c \
+ mm-generic-cdma.h \
+ mm-generic-gsm.c \
+ mm-generic-gsm.h \
mm-modem-cdma.c \
mm-modem-cdma.h \
mm-modem-gsm-card.c \
@@ -37,10 +47,8 @@ modem_manager_SOURCES = \
mm-options.h \
mm-plugin.c \
mm-plugin.h \
- mm-serial.c \
- mm-serial.h \
- mm-serial-parsers.c \
- mm-serial-parsers.h
+ mm-plugin-base.c \
+ mm-plugin-base.h
mm-manager-glue.h: $(top_srcdir)/introspection/mm-manager.xml
dbus-binding-tool --prefix=mm_manager --mode=glib-server --output=$@ $<
diff --git a/src/main.c b/src/main.c
index 629b10ed..36691150 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,21 +1,40 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#include <signal.h>
#include <syslog.h>
#include <string.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <libhal.h>
#include "mm-manager.h"
#include "mm-options.h"
#define HAL_DBUS_SERVICE "org.freedesktop.Hal"
+static GMainLoop *loop = NULL;
+
static void
mm_signal_handler (int signo)
{
if (signo == SIGUSR1)
mm_options_set_debug (!mm_options_debug ());
+ else if (signo == SIGINT || signo == SIGTERM) {
+ g_message ("Caught signal %d, shutting down...", signo);
+ g_main_loop_quit (loop);
+ }
}
static void
@@ -28,7 +47,9 @@ setup_signals (void)
action.sa_handler = mm_signal_handler;
action.sa_mask = mask;
action.sa_flags = 0;
- sigaction (SIGUSR1, &action, NULL);
+ sigaction (SIGUSR1, &action, NULL);
+ sigaction (SIGTERM, &action, NULL);
+ sigaction (SIGINT, &action, NULL);
}
static void
@@ -89,8 +110,6 @@ logging_shutdown (void)
static void
destroy_cb (DBusGProxy *proxy, gpointer user_data)
{
- GMainLoop *loop = (GMainLoop *) user_data;
-
g_message ("disconnected from the system bus, exiting.");
g_main_loop_quit (loop);
}
@@ -135,87 +154,11 @@ create_dbus_proxy (DBusGConnection *bus)
return proxy;
}
-static void
-hal_init (MMManager *manager)
-{
- LibHalContext *hal_ctx;
- DBusError dbus_error;
-
- hal_ctx = libhal_ctx_new ();
- if (!hal_ctx) {
- g_warning ("Could not get connection to the HAL service.");
- }
-
- libhal_ctx_set_dbus_connection (hal_ctx, dbus_g_connection_get_connection (mm_manager_get_bus (manager)));
-
- dbus_error_init (&dbus_error);
- if (!libhal_ctx_init (hal_ctx, &dbus_error)) {
- g_warning ("libhal_ctx_init() failed: %s", dbus_error.message);
- dbus_error_free (&dbus_error);
- }
-
- mm_manager_set_hal_ctx (manager, hal_ctx);
-}
-
-static void
-hal_deinit (MMManager *manager)
-{
- LibHalContext *hal_ctx;
-
- hal_ctx = mm_manager_get_hal_ctx (manager);
- if (hal_ctx) {
- libhal_ctx_shutdown (hal_ctx, NULL);
- libhal_ctx_free (hal_ctx);
- mm_manager_set_hal_ctx (manager, NULL);
- }
-}
-
static gboolean
-hal_on_bus (DBusGProxy *proxy)
+start_manager (gpointer user_data)
{
- GError *err = NULL;
- gboolean has_owner = FALSE;
-
- if (!dbus_g_proxy_call (proxy,
- "NameHasOwner", &err,
- G_TYPE_STRING, HAL_DBUS_SERVICE,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &has_owner,
- G_TYPE_INVALID)) {
- g_warning ("Error on NameHasOwner DBUS call: %s", err->message);
- g_error_free (err);
- }
-
- return has_owner;
-}
-
-static void
-name_owner_changed (DBusGProxy *proxy,
- const char *name,
- const char *old_owner,
- const char *new_owner,
- gpointer user_data)
-{
- MMManager *manager;
- gboolean old_owner_good;
- gboolean new_owner_good;
-
- /* Only care about signals from HAL */
- if (strcmp (name, HAL_DBUS_SERVICE))
- return;
-
- manager = MM_MANAGER (user_data);
- old_owner_good = (old_owner && (strlen (old_owner) > 0));
- new_owner_good = (new_owner && (strlen (new_owner) > 0));
-
- if (!old_owner_good && new_owner_good) {
- g_message ("HAL appeared");
- hal_init (manager);
- } else if (old_owner_good && !new_owner_good) {
- /* HAL went away. Bad HAL. */
- g_message ("HAL disappeared");
- hal_deinit (manager);
- }
+ mm_manager_start (MM_MANAGER (user_data));
+ return FALSE;
}
int
@@ -223,9 +166,9 @@ main (int argc, char *argv[])
{
DBusGConnection *bus;
DBusGProxy *proxy;
- GMainLoop *loop;
MMManager *manager;
GError *err = NULL;
+ guint id;
mm_options_parse (argc, argv);
g_type_init ();
@@ -249,21 +192,15 @@ main (int argc, char *argv[])
return -1;
manager = mm_manager_new (bus);
-
- dbus_g_proxy_connect_signal (proxy,
- "NameOwnerChanged",
- G_CALLBACK (name_owner_changed),
- manager, NULL);
-
- if (hal_on_bus (proxy))
- hal_init (manager);
+ g_idle_add (start_manager, manager);
loop = g_main_loop_new (NULL, FALSE);
- g_signal_connect (proxy, "destroy", G_CALLBACK (destroy_cb), loop);
+ id = g_signal_connect (proxy, "destroy", G_CALLBACK (destroy_cb), loop);
g_main_loop_run (loop);
- hal_deinit (manager);
+ g_signal_handler_disconnect (proxy, id);
+
g_object_unref (manager);
g_object_unref (proxy);
dbus_g_connection_unref (bus);
diff --git a/src/mm-errors.c b/src/mm-errors.c
index 380ca2f1..e313f0f4 100644
--- a/src/mm-errors.c
+++ b/src/mm-errors.c
@@ -52,7 +52,7 @@ mm_modem_error_get_type (void)
if (etype == 0) {
static const GEnumValue values[] = {
- ENUM_ENTRY (MM_MODEM_ERROR_GENERAL, "Generial"),
+ ENUM_ENTRY (MM_MODEM_ERROR_GENERAL, "General"),
ENUM_ENTRY (MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, "OperationNotSupported"),
{ 0, 0, 0 }
};
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c
index de8c916a..7d731384 100644
--- a/src/mm-generic-cdma.c
+++ b/src/mm-generic-cdma.c
@@ -6,6 +6,7 @@
#include "mm-generic-cdma.h"
#include "mm-modem-cdma.h"
#include "mm-modem-simple.h"
+#include "mm-serial-port.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
#include "mm-serial-parsers.h"
@@ -16,25 +17,152 @@ static gpointer mm_generic_cdma_parent_class = NULL;
typedef struct {
char *driver;
+ char *plugin;
+ char *device;
+
+ guint32 ip_method;
+ gboolean valid;
+
+ MMSerialPort *primary;
+ MMSerialPort *secondary;
+ MMPort *data;
} MMGenericCdmaPrivate;
MMModem *
-mm_generic_cdma_new (const char *serial_device, const char *driver)
+mm_generic_cdma_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (serial_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_GENERIC_CDMA,
- MM_SERIAL_DEVICE, serial_device,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_CDMA,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
+static const char *
+strip_response (const char *resp, const char *cmd)
+{
+ const char *p = resp;
+
+ if (p) {
+ if (!strncmp (p, cmd, strlen (cmd)))
+ p += strlen (cmd);
+ while (*p == ' ')
+ p++;
+ }
+ return p;
+}
+
/*****************************************************************************/
static void
-enable_error_reporting_done (MMSerial *serial,
+check_valid (MMGenericCdma *self)
+{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self);
+ gboolean new_valid = FALSE;
+
+ if (priv->primary && priv->data)
+ new_valid = TRUE;
+
+ if (priv->valid != new_valid) {
+ priv->valid = new_valid;
+ g_object_notify (G_OBJECT (self), MM_MODEM_VALID);
+ }
+}
+
+static gboolean
+owns_port (MMModem *modem, const char *subsys, const char *name)
+{
+ return !!mm_modem_base_get_port (MM_MODEM_BASE (modem), subsys, name);
+}
+
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericCdma *self = MM_GENERIC_CDMA (modem);
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+ MMPort *port;
+
+ g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), FALSE);
+
+ if (!strcmp (subsys, "tty")) {
+ if (!priv->primary)
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (!priv->secondary)
+ ptype = MM_PORT_TYPE_SECONDARY;
+ }
+
+ port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype);
+ if (MM_IS_SERIAL_PORT (port)) {
+ g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL);
+ mm_serial_port_set_response_parser (MM_SERIAL_PORT (port),
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
+ }
+
+ if (MM_IS_SERIAL_PORT (port)) {
+ if (ptype == MM_PORT_TYPE_PRIMARY) {
+ priv->primary = MM_SERIAL_PORT (port);
+ if (!priv->data) {
+ priv->data = port;
+ g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
+ }
+ check_valid (self);
+ } else if (ptype == MM_PORT_TYPE_SECONDARY)
+ priv->secondary = MM_SERIAL_PORT (port);
+ } else {
+ /* Net device (if any) is the preferred data port */
+ if (!priv->data || MM_IS_SERIAL_PORT (priv->data)) {
+ priv->data = port;
+ g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
+ check_valid (self);
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+release_port (MMModem *modem, const char *subsys, const char *name)
+{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
+ MMPort *port;
+
+ port = mm_modem_base_get_port (MM_MODEM_BASE (modem), subsys, name);
+ if (!port)
+ return;
+
+ if (port == MM_PORT (priv->primary)) {
+ mm_modem_base_remove_port (MM_MODEM_BASE (modem), port);
+ priv->primary = NULL;
+ }
+
+ if (port == priv->data) {
+ priv->data = NULL;
+ g_object_notify (G_OBJECT (modem), MM_MODEM_DATA_DEVICE);
+ }
+
+ if (port == MM_PORT (priv->secondary)) {
+ mm_modem_base_remove_port (MM_MODEM_BASE (modem), port);
+ priv->secondary = NULL;
+ }
+
+ check_valid (MM_GENERIC_CDMA (modem));
+}
+
+static void
+enable_error_reporting_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -49,7 +177,7 @@ enable_error_reporting_done (MMSerial *serial,
}
static void
-init_done (MMSerial *serial,
+init_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -65,14 +193,14 @@ init_done (MMSerial *serial,
FIXME: It's mandatory by spec, so it really shouldn't be optional. Figure
out which CDMA modems have problems with it and implement plugin for them.
*/
- mm_serial_queue_command (serial, "+CMEE=1", 3, enable_error_reporting_done, user_data);
+ mm_serial_port_queue_command (port, "+CMEE=1", 3, enable_error_reporting_done, user_data);
}
}
static void
-flash_done (MMSerial *serial, gpointer user_data)
+flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "Z E0 V1 X4 &C1", 3, init_done, user_data);
+ mm_serial_port_queue_command (port, "Z E0 V1 X4 &C1", 3, init_done, user_data);
}
static void
@@ -81,25 +209,26 @@ enable (MMModem *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
info = mm_callback_info_new (modem, callback, user_data);
if (!do_enable) {
- mm_serial_close (MM_SERIAL (modem));
+ mm_serial_port_close (priv->primary);
mm_callback_info_schedule (info);
return;
}
- if (mm_serial_open (MM_SERIAL (modem), &info->error))
- mm_serial_flash (MM_SERIAL (modem), 100, flash_done, info);
+ if (mm_serial_port_open (priv->primary, &info->error))
+ mm_serial_port_flash (priv->primary, 100, flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
}
static void
-dial_done (MMSerial *serial,
+dial_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -118,17 +247,18 @@ connect (MMModem *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
char *command;
info = mm_callback_info_new (modem, callback, user_data);
command = g_strconcat ("DT", number, NULL);
- mm_serial_queue_command (MM_SERIAL (modem), command, 60, dial_done, info);
+ mm_serial_port_queue_command (priv->primary, command, 60, dial_done, info);
g_free (command);
}
static void
-disconnect_flash_done (MMSerial *serial, gpointer user_data)
+disconnect_flash_done (MMSerialPort *port, gpointer user_data)
{
mm_callback_info_schedule ((MMCallbackInfo *) user_data);
}
@@ -138,14 +268,99 @@ disconnect (MMModem *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
+ g_return_if_fail (priv->primary != NULL);
+
info = mm_callback_info_new (modem, callback, user_data);
- mm_serial_flash (MM_SERIAL (modem), 1000, disconnect_flash_done, info);
+ mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info);
+}
+
+static void
+card_info_invoke (MMCallbackInfo *info)
+{
+ MMModemInfoFn callback = (MMModemInfoFn) info->callback;
+
+ callback (info->modem,
+ (char *) mm_callback_info_get_data (info, "card-info-manufacturer"),
+ (char *) mm_callback_info_get_data (info, "card-info-model"),
+ (char *) mm_callback_info_get_data (info, "card-info-version"),
+ info->error, info->user_data);
+}
+
+static void
+get_version_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ const char *p;
+
+ if (!error) {
+ p = strip_response (response->str, "+GMR:");
+ mm_callback_info_set_data (info, "card-info-version", g_strdup (p), g_free);
+ } else if (!info->error)
+ info->error = g_error_copy (error);
+
+ mm_callback_info_schedule (info);
+}
+
+static void
+get_model_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ const char *p;
+
+ if (!error) {
+ p = strip_response (response->str, "+GMM:");
+ mm_callback_info_set_data (info, "card-info-model", g_strdup (p), g_free);
+ } else if (!info->error)
+ info->error = g_error_copy (error);
+}
+
+static void
+get_manufacturer_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ const char *p;
+
+ if (!error) {
+ p = strip_response (response->str, "+GMI:");
+ mm_callback_info_set_data (info, "card-info-manufacturer", g_strdup (p), g_free);
+ } else
+ info->error = g_error_copy (error);
+}
+
+static void
+get_card_info (MMModem *modem,
+ MMModemInfoFn callback,
+ gpointer user_data)
+{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (MM_MODEM (modem),
+ card_info_invoke,
+ G_CALLBACK (callback),
+ user_data);
+
+ mm_serial_port_queue_command_cached (priv->primary, "+GMI", 3, get_manufacturer_done, info);
+ mm_serial_port_queue_command_cached (priv->primary, "+GMM", 3, get_model_done, info);
+ mm_serial_port_queue_command_cached (priv->primary, "+GMR", 3, get_version_done, info);
}
+/*****************************************************************************/
+
static void
-get_signal_quality_done (MMSerial *serial,
+get_signal_quality_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -157,18 +372,22 @@ get_signal_quality_done (MMSerial *serial,
info->error = g_error_copy (error);
else if (!strncmp (reply, "+CSQ: ", 6)) {
/* Got valid reply */
- int quality;
- int ber;
+ int quality, ber;
reply += 6;
if (sscanf (reply, "%d,%d", &quality, &ber)) {
- /* 99 means unknown */
- if (quality != 99)
+ /* 99 means unknown/no service */
+ if (quality == 99) {
+ info->error = g_error_new_literal (MM_MOBILE_ERROR,
+ MM_MOBILE_ERROR_NO_NETWORK,
+ "No service");
+ } else {
/* Normalize the quality */
- quality = quality * 100 / 31;
+ quality = CLAMP (quality, 0, 31) * 100 / 31;
- mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
+ }
} else
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"%s", "Could not parse signal quality results");
@@ -182,10 +401,129 @@ get_signal_quality (MMModemCdma *modem,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "+CSQ", 3, get_signal_quality_done, info);
+ /* Prefer secondary port for signal strength */
+ mm_serial_port_queue_command (priv->secondary ? priv->secondary : priv->primary,
+ "+CSQ",
+ 3,
+ get_signal_quality_done, info);
+}
+
+static void
+get_string_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ const char *p;
+
+ if (error)
+ info->error = g_error_copy (error);
+ else {
+ p = strip_response (response->str, "+GSN:");
+ mm_callback_info_set_result (info, g_strdup (p), g_free);
+ }
+
+ mm_callback_info_schedule (info);
+}
+
+static void
+get_esn (MMModemCdma *modem,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
+ mm_serial_port_queue_command_cached (priv->primary, "+GSN", 3, get_string_done, info);
+}
+
+static void
+serving_system_invoke (MMCallbackInfo *info)
+{
+ MMModemCdmaServingSystemFn callback = (MMModemCdmaServingSystemFn) info->callback;
+
+ callback (MM_MODEM_CDMA (info->modem),
+ GPOINTER_TO_UINT (mm_callback_info_get_data (info, "class")),
+ (char) GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band")),
+ GPOINTER_TO_UINT (mm_callback_info_get_data (info, "sid")),
+ info->error,
+ info->user_data);
+}
+
+static void
+serving_system_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ char *reply = response->str;
+ int class = 0, sid = 99999, num;
+ char band = 'Z';
+
+ if (error) {
+ info->error = g_error_copy (error);
+ goto out;
+ }
+
+ if (!strstr (reply, "+CSS: ")) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse Serving System results.");
+ goto out;
+ }
+
+ /* Got valid reply */
+ reply += 6;
+
+ num = sscanf (reply, "%d, %c, %d", &class, &band, &sid);
+ if (num != 3)
+ num = sscanf (reply, "%d,%c,%d", &class, &band, &sid);
+
+ if (num == 3) {
+ /* Normalize */
+ class = CLAMP (class, 0, 4);
+ band = CLAMP (band, 'A', 'Z');
+ if (sid < 0 || sid > 32767)
+ sid = 99999;
+
+ /* 99 means unknown/no service */
+ if (sid == 99999) {
+ info->error = g_error_new_literal (MM_MOBILE_ERROR,
+ MM_MOBILE_ERROR_NO_NETWORK,
+ "No service");
+ } else {
+ mm_callback_info_set_data (info, "class", GUINT_TO_POINTER (class), NULL);
+ mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (band), NULL);
+ mm_callback_info_set_data (info, "sid", GUINT_TO_POINTER (sid), NULL);
+ }
+ } else
+ info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "%s", "Could not parse signal quality results");
+
+ out:
+ mm_callback_info_schedule (info);
+}
+
+static void
+get_serving_system (MMModemCdma *modem,
+ MMModemCdmaServingSystemFn callback,
+ gpointer user_data)
+{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (MM_MODEM (modem),
+ serving_system_invoke,
+ G_CALLBACK (callback),
+ user_data);
+
+ mm_serial_port_queue_command (priv->primary, "+CSS?", 3, serving_system_done, info);
}
/*****************************************************************************/
@@ -261,6 +599,7 @@ simple_connect (MMModemSimple *simple,
gpointer user_data)
{
MMCallbackInfo *info;
+ GError *error = NULL;
info = mm_callback_info_new (MM_MODEM (simple), callback, user_data);
mm_callback_info_set_data (info, "simple-connect-properties",
@@ -268,12 +607,12 @@ simple_connect (MMModemSimple *simple,
(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");
+ if (!simple_get_string_property (info, "number", &error)) {
+ if (!error)
+ error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Missing number property");
}
- simple_state_machine (MM_MODEM (simple), NULL, info);
+ simple_state_machine (MM_MODEM (simple), error, info);
}
static void
@@ -340,15 +679,21 @@ simple_get_status (MMModemSimple *simple,
static void
modem_init (MMModem *modem_class)
{
+ modem_class->owns_port = owns_port;
+ modem_class->grab_port = grab_port;
+ modem_class->release_port = release_port;
modem_class->enable = enable;
modem_class->connect = connect;
modem_class->disconnect = disconnect;
+ modem_class->get_info = get_card_info;
}
static void
modem_cdma_init (MMModemCdma *cdma_modem_class)
{
cdma_modem_class->get_signal_quality = get_signal_quality;
+ cdma_modem_class->get_esn = get_esn;
+ cdma_modem_class->get_serving_system = get_serving_system;
}
static void
@@ -361,24 +706,32 @@ modem_simple_init (MMModemSimple *class)
static void
mm_generic_cdma_init (MMGenericCdma *self)
{
- mm_serial_set_response_parser (MM_SERIAL (self),
- mm_serial_parser_v1_parse,
- mm_serial_parser_v1_new (),
- mm_serial_parser_v1_destroy);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (object);
+
switch (prop_id) {
case MM_MODEM_PROP_DRIVER:
/* Construct only */
- MM_GENERIC_CDMA_GET_PRIVATE (object)->driver = g_value_dup_string (value);
+ priv->driver = g_value_dup_string (value);
+ break;
+ case MM_MODEM_PROP_PLUGIN:
+ /* Construct only */
+ priv->plugin = g_value_dup_string (value);
+ break;
+ case MM_MODEM_PROP_MASTER_DEVICE:
+ /* Constrcut only */
+ priv->device = g_value_dup_string (value);
break;
- case MM_MODEM_PROP_DEVICE:
- case MM_MODEM_PROP_TYPE:
case MM_MODEM_PROP_IP_METHOD:
+ priv->ip_method = g_value_get_uint (value);
+ break;
+ case MM_MODEM_PROP_TYPE:
+ case MM_MODEM_PROP_VALID:
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -390,18 +743,32 @@ static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
+ MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (object);
+
switch (prop_id) {
- case MM_MODEM_PROP_DEVICE:
- g_value_set_string (value, mm_serial_get_device (MM_SERIAL (object)));
+ case MM_MODEM_PROP_DATA_DEVICE:
+ if (priv->data)
+ g_value_set_string (value, mm_port_get_device (priv->data));
+ else
+ g_value_set_string (value, NULL);
+ break;
+ case MM_MODEM_PROP_MASTER_DEVICE:
+ g_value_set_string (value, priv->device);
break;
case MM_MODEM_PROP_DRIVER:
- g_value_set_string (value, MM_GENERIC_CDMA_GET_PRIVATE (object)->driver);
+ g_value_set_string (value, priv->driver);
+ break;
+ case MM_MODEM_PROP_PLUGIN:
+ g_value_set_string (value, priv->plugin);
break;
case MM_MODEM_PROP_TYPE:
g_value_set_uint (value, MM_MODEM_TYPE_CDMA);
break;
case MM_MODEM_PROP_IP_METHOD:
- g_value_set_uint (value, MM_MODEM_IP_METHOD_PPP);
+ g_value_set_uint (value, priv->ip_method);
+ break;
+ case MM_MODEM_PROP_VALID:
+ g_value_set_boolean (value, priv->valid);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -434,20 +801,32 @@ mm_generic_cdma_class_init (MMGenericCdmaClass *klass)
/* Properties */
g_object_class_override_property (object_class,
- MM_MODEM_PROP_DEVICE,
- MM_MODEM_DEVICE);
+ MM_MODEM_PROP_DATA_DEVICE,
+ MM_MODEM_DATA_DEVICE);
+
+ g_object_class_override_property (object_class,
+ MM_MODEM_PROP_MASTER_DEVICE,
+ MM_MODEM_MASTER_DEVICE);
g_object_class_override_property (object_class,
MM_MODEM_PROP_DRIVER,
MM_MODEM_DRIVER);
g_object_class_override_property (object_class,
+ MM_MODEM_PROP_PLUGIN,
+ MM_MODEM_PLUGIN);
+
+ g_object_class_override_property (object_class,
MM_MODEM_PROP_TYPE,
MM_MODEM_TYPE);
g_object_class_override_property (object_class,
MM_MODEM_PROP_IP_METHOD,
MM_MODEM_IP_METHOD);
+
+ g_object_class_override_property (object_class,
+ MM_MODEM_PROP_VALID,
+ MM_MODEM_VALID);
}
GType
@@ -480,7 +859,10 @@ mm_generic_cdma_get_type (void)
(GInterfaceInitFunc) modem_simple_init
};
- generic_cdma_type = g_type_register_static (MM_TYPE_SERIAL, "MMGenericCdma", &generic_cdma_type_info, 0);
+ generic_cdma_type = g_type_register_static (MM_TYPE_MODEM_BASE,
+ "MMGenericCdma",
+ &generic_cdma_type_info,
+ 0);
g_type_add_interface_static (generic_cdma_type, MM_TYPE_MODEM, &modem_iface_info);
g_type_add_interface_static (generic_cdma_type, MM_TYPE_MODEM_CDMA, &modem_cdma_iface_info);
diff --git a/src/mm-generic-cdma.h b/src/mm-generic-cdma.h
index 125b540a..44fea73b 100644
--- a/src/mm-generic-cdma.h
+++ b/src/mm-generic-cdma.h
@@ -4,26 +4,27 @@
#define MM_GENERIC_CDMA_H
#include "mm-modem.h"
-#include "mm-serial.h"
+#include "mm-modem-base.h"
-#define MM_TYPE_GENERIC_CDMA (mm_generic_cdma_get_type ())
-#define MM_GENERIC_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_GENERIC_CDMA, MMGenericCdma))
-#define MM_GENERIC_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_GENERIC_CDMA, MMGenericCdmaClass))
-#define MM_IS_GENERIC_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_GENERIC_CDMA))
-#define MM_IS_GENERIC_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_GENERIC_CDMA))
-#define MM_GENERIC_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_GENERIC_CDMA, MMGenericCdmaClass))
+#define MM_TYPE_GENERIC_CDMA (mm_generic_cdma_get_type ())
+#define MM_GENERIC_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_GENERIC_CDMA, MMGenericCdma))
+#define MM_GENERIC_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_GENERIC_CDMA, MMGenericCdmaClass))
+#define MM_IS_GENERIC_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_GENERIC_CDMA))
+#define MM_IS_GENERIC_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_GENERIC_CDMA))
+#define MM_GENERIC_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_GENERIC_CDMA, MMGenericCdmaClass))
typedef struct {
- MMSerial parent;
+ MMModemBase parent;
} MMGenericCdma;
typedef struct {
- MMSerialClass parent;
+ MMModemBaseClass parent;
} MMGenericCdmaClass;
GType mm_generic_cdma_get_type (void);
-MMModem *mm_generic_cdma_new (const char *serial_device,
- const char *driver);
+MMModem *mm_generic_cdma_new (const char *device,
+ const char *driver,
+ const char *plugin);
#endif /* MM_GENERIC_CDMA_H */
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index a723a533..06bfff6e 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -18,10 +18,14 @@ static gpointer mm_generic_gsm_parent_class = NULL;
typedef struct {
char *driver;
+ char *plugin;
+ char *device;
+
+ gboolean valid;
+
char *data_device;
char *oper_code;
char *oper_name;
- guint32 modem_type;
guint32 ip_method;
gboolean unsolicited_registration;
@@ -30,24 +34,40 @@ typedef struct {
guint32 signal_quality;
guint32 cid;
+
+ MMSerialPort *primary;
+ MMSerialPort *secondary;
+ MMPort *data;
} MMGenericGsmPrivate;
-static void get_registration_status (MMSerial *serial, MMCallbackInfo *info);
-static void read_operator_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data);
+static void get_registration_status (MMSerialPort *port, MMCallbackInfo *info);
+static void read_operator_code_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data);
+
+static void read_operator_name_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data);
+
+static void reg_state_changed (MMSerialPort *port,
+ GMatchInfo *match_info,
+ gpointer user_data);
MMModem *
-mm_generic_gsm_new (const char *serial_device, const char *driver)
+mm_generic_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin)
{
- g_return_val_if_fail (serial_device != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (plugin != NULL, NULL);
return MM_MODEM (g_object_new (MM_TYPE_GENERIC_GSM,
- MM_SERIAL_DEVICE, serial_device,
+ MM_MODEM_MASTER_DEVICE, device,
MM_MODEM_DRIVER, driver,
- MM_MODEM_TYPE, MM_MODEM_TYPE_GSM,
+ MM_MODEM_PLUGIN, plugin,
NULL));
}
@@ -101,8 +121,8 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
if (status == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
- mm_serial_queue_command (MM_SERIAL (modem), "+COPS=3,2;+COPS?", 3, read_operator_done, GINT_TO_POINTER (0));
- mm_serial_queue_command (MM_SERIAL (modem), "+COPS=3,0;+COPS?", 3, read_operator_done, GINT_TO_POINTER (1));
+ mm_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem);
+ mm_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem);
mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL);
} else {
g_free (priv->oper_code);
@@ -116,7 +136,7 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
}
static void
-pin_check_done (MMSerial *serial,
+pin_check_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -150,18 +170,138 @@ mm_generic_gsm_check_pin (MMGenericGsm *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv;
MMCallbackInfo *info;
g_return_if_fail (MM_IS_GENERIC_GSM (modem));
+ priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "+CPIN?", 3, pin_check_done, info);
+ mm_serial_port_queue_command (priv->primary, "+CPIN?", 3, pin_check_done, info);
}
/*****************************************************************************/
static void
-enable_done (MMSerial *serial,
+check_valid (MMGenericGsm *self)
+{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ gboolean new_valid = FALSE;
+
+ if (priv->primary && priv->data)
+ new_valid = TRUE;
+
+ if (priv->valid != new_valid) {
+ priv->valid = new_valid;
+ g_object_notify (G_OBJECT (self), MM_MODEM_VALID);
+ }
+}
+
+static gboolean
+owns_port (MMModem *modem, const char *subsys, const char *name)
+{
+ return !!mm_modem_base_get_port (MM_MODEM_BASE (modem), subsys, name);
+}
+
+MMPort *
+mm_generic_gsm_grab_port (MMGenericGsm *self,
+ const char *subsys,
+ const char *name,
+ MMPortType ptype,
+ GError **error)
+{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ MMPort *port = NULL;
+ GRegex *regex;
+
+ g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), FALSE);
+
+ port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype);
+ if (MM_IS_SERIAL_PORT (port)) {
+ mm_serial_port_set_response_parser (MM_SERIAL_PORT (port),
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
+
+ regex = g_regex_new ("\\r\\n\\+CREG: (\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, reg_state_changed, self, NULL);
+ g_regex_unref (regex);
+
+ if (ptype == MM_PORT_TYPE_PRIMARY) {
+ priv->primary = MM_SERIAL_PORT (port);
+ if (!priv->data) {
+ priv->data = port;
+ g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
+ }
+ check_valid (self);
+ } else if (ptype == MM_PORT_TYPE_SECONDARY)
+ priv->secondary = MM_SERIAL_PORT (port);
+ } else {
+ /* Net device (if any) is the preferred data port */
+ if (!priv->data || MM_IS_SERIAL_PORT (priv->data)) {
+ priv->data = port;
+ g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
+ check_valid (self);
+ }
+ }
+
+ return port;
+}
+
+static gboolean
+grab_port (MMModem *modem,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ MMGenericGsm *self = MM_GENERIC_GSM (modem);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ MMPortType ptype = MM_PORT_TYPE_IGNORED;
+
+ if (!strcmp (subsys, "tty")) {
+ if (!priv->primary)
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (!priv->secondary)
+ ptype = MM_PORT_TYPE_SECONDARY;
+ }
+
+ return !!mm_generic_gsm_grab_port (self, subsys, name, ptype, error);
+}
+
+static void
+release_port (MMModem *modem, const char *subsys, const char *name)
+{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ MMPort *port;
+
+ if (strcmp (subsys, "tty"))
+ return;
+
+ port = mm_modem_base_get_port (MM_MODEM_BASE (modem), subsys, name);
+ if (!port)
+ return;
+
+ if (port == MM_PORT (priv->primary)) {
+ mm_modem_base_remove_port (MM_MODEM_BASE (modem), port);
+ priv->primary = NULL;
+ }
+
+ if (port == priv->data) {
+ priv->data = NULL;
+ g_object_notify (G_OBJECT (modem), MM_MODEM_DATA_DEVICE);
+ }
+
+ if (port == MM_PORT (priv->secondary)) {
+ mm_modem_base_remove_port (MM_MODEM_BASE (modem), port);
+ priv->secondary = NULL;
+ }
+
+ check_valid (MM_GENERIC_GSM (modem));
+}
+
+static void
+enable_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -175,46 +315,65 @@ enable_done (MMSerial *serial,
}
static void
-init_done (MMSerial *serial,
+init_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ char *cmd = NULL;
if (error) {
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
} else {
- if (MM_GENERIC_GSM_GET_PRIVATE (serial)->unsolicited_registration)
- mm_serial_queue_command (serial, "+CREG=1", 5, NULL, NULL);
+ if (MM_GENERIC_GSM_GET_PRIVATE (info->modem)->unsolicited_registration)
+ mm_serial_port_queue_command (port, "+CREG=1", 5, NULL, NULL);
else
- mm_serial_queue_command (serial, "+CREG=0", 5, NULL, NULL);
+ mm_serial_port_queue_command (port, "+CREG=0", 5, NULL, NULL);
- mm_serial_queue_command (serial, "+CFUN=1", 5, enable_done, user_data);
+ g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL);
+ if (cmd && strlen (cmd))
+ mm_serial_port_queue_command (port, cmd, 5, enable_done, user_data);
+ else
+ enable_done (port, NULL, NULL, user_data);
+ g_free (cmd);
}
}
static void
-enable_flash_done (MMSerial *serial, gpointer user_data)
+enable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "Z E0 V1 X4 &C1 +CMEE=1", 3, init_done, user_data);
+ MMCallbackInfo *info = user_data;
+ char *cmd = NULL;
+
+ g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_INIT_CMD, &cmd, NULL);
+ mm_serial_port_queue_command (port, cmd, 3, init_done, user_data);
+ g_free (cmd);
}
static void
-disable_done (MMSerial *serial,
+disable_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
- mm_serial_close (serial);
+ mm_serial_port_close (port);
mm_callback_info_schedule ((MMCallbackInfo *) user_data);
}
static void
-disable_flash_done (MMSerial *serial, gpointer user_data)
+disable_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_serial_queue_command (serial, "+CFUN=0", 5, disable_done, user_data);
+ MMCallbackInfo *info = user_data;
+ char *cmd = NULL;
+
+ g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL);
+ if (cmd && strlen (cmd))
+ mm_serial_port_queue_command (port, cmd, 5, disable_done, user_data);
+ else
+ disable_done (port, NULL, NULL, user_data);
+ g_free (cmd);
}
static void
@@ -223,6 +382,7 @@ enable (MMModem *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
/* First, reset the previously used CID */
@@ -233,13 +393,13 @@ enable (MMModem *modem,
if (!do_enable) {
mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem));
- if (mm_serial_is_connected (MM_SERIAL (modem)))
- mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info);
+ if (mm_serial_port_is_connected (priv->primary))
+ mm_serial_port_flash (priv->primary, 1000, disable_flash_done, info);
else
- disable_flash_done (MM_SERIAL (modem), info);
+ disable_flash_done (priv->primary, info);
} else {
- if (mm_serial_open (MM_SERIAL (modem), &info->error))
- mm_serial_flash (MM_SERIAL (modem), 100, enable_flash_done, info);
+ if (mm_serial_port_open (priv->primary, &info->error))
+ mm_serial_port_flash (priv->primary, 100, enable_flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
@@ -247,7 +407,7 @@ enable (MMModem *modem,
}
static void
-get_string_done (MMSerial *serial,
+get_string_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -267,10 +427,11 @@ get_imei (MMModemGsmCard *modem,
MMModemStringFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command_cached (MM_SERIAL (modem), "+CGSN", 3, get_string_done, info);
+ mm_serial_port_queue_command_cached (priv->primary, "+CGSN", 3, get_string_done, info);
}
static void
@@ -278,18 +439,19 @@ get_imsi (MMModemGsmCard *modem,
MMModemStringFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command_cached (MM_SERIAL (modem), "+CIMI", 3, get_string_done, info);
+ mm_serial_port_queue_command_cached (priv->primary, "+CIMI", 3, get_string_done, info);
}
static void
-gsm_card_info_invoke (MMCallbackInfo *info)
+card_info_invoke (MMCallbackInfo *info)
{
- MMModemGsmCardInfoFn callback = (MMModemGsmCardInfoFn) info->callback;
+ MMModemInfoFn callback = (MMModemInfoFn) info->callback;
- callback (MM_MODEM_GSM_CARD (info->modem),
+ callback (info->modem,
(char *) mm_callback_info_get_data (info, "card-info-manufacturer"),
(char *) mm_callback_info_get_data (info, "card-info-model"),
(char *) mm_callback_info_get_data (info, "card-info-version"),
@@ -297,7 +459,7 @@ gsm_card_info_invoke (MMCallbackInfo *info)
}
static void
-get_version_done (MMSerial *serial,
+get_version_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -313,7 +475,7 @@ get_version_done (MMSerial *serial,
}
static void
-get_model_done (MMSerial *serial,
+get_model_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -327,7 +489,7 @@ get_model_done (MMSerial *serial,
}
static void
-get_manufacturer_done (MMSerial *serial,
+get_manufacturer_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -341,25 +503,25 @@ get_manufacturer_done (MMSerial *serial,
}
static void
-get_card_info (MMModemGsmCard *modem,
- MMModemGsmCardInfoFn callback,
+get_card_info (MMModem *modem,
+ MMModemInfoFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
- MMSerial *serial = MM_SERIAL (modem);
info = mm_callback_info_new_full (MM_MODEM (modem),
- gsm_card_info_invoke,
+ card_info_invoke,
G_CALLBACK (callback),
user_data);
- mm_serial_queue_command_cached (serial, "+CGMI", 3, get_manufacturer_done, info);
- mm_serial_queue_command_cached (serial, "+CGMM", 3, get_model_done, info);
- mm_serial_queue_command_cached (serial, "+CGMR", 3, get_version_done, info);
+ mm_serial_port_queue_command_cached (priv->primary, "+CGMI", 3, get_manufacturer_done, info);
+ mm_serial_port_queue_command_cached (priv->primary, "+CGMM", 3, get_model_done, info);
+ mm_serial_port_queue_command_cached (priv->primary, "+CGMR", 3, get_version_done, info);
}
static void
-send_puk_done (MMSerial *serial,
+send_puk_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -378,17 +540,18 @@ send_puk (MMModemGsmCard *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
char *command;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
command = g_strdup_printf ("+CPIN=\"%s\",\"%s\"", puk, pin);
- mm_serial_queue_command (MM_SERIAL (modem), command, 3, send_puk_done, info);
+ mm_serial_port_queue_command (priv->primary, command, 3, send_puk_done, info);
g_free (command);
}
static void
-send_pin_done (MMSerial *serial,
+send_pin_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -406,17 +569,18 @@ send_pin (MMModemGsmCard *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
char *command;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
command = g_strdup_printf ("+CPIN=\"%s\"", pin);
- mm_serial_queue_command (MM_SERIAL (modem), command, 3, send_pin_done, info);
+ mm_serial_port_queue_command (priv->primary, command, 3, send_pin_done, info);
g_free (command);
}
static void
-enable_pin_done (MMSerial *serial,
+enable_pin_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -435,17 +599,18 @@ enable_pin (MMModemGsmCard *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
char *command;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
command = g_strdup_printf ("+CLCK=\"SC\",%d,\"%s\"", enabled ? 1 : 0, pin);
- mm_serial_queue_command (MM_SERIAL (modem), command, 3, enable_pin_done, info);
+ mm_serial_port_queue_command (priv->primary, command, 3, enable_pin_done, info);
g_free (command);
}
static void
-change_pin_done (MMSerial *serial,
+change_pin_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -464,12 +629,13 @@ change_pin (MMModemGsmCard *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
char *command;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
command = g_strdup_printf ("+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin);
- mm_serial_queue_command (MM_SERIAL (modem), command, 3, change_pin_done, info);
+ mm_serial_port_queue_command (priv->primary, command, 3, change_pin_done, info);
g_free (command);
}
@@ -500,30 +666,48 @@ parse_operator (const char *reply)
}
static void
-read_operator_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+read_operator_code_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- if (!error) {
- char *oper;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
+ char *oper;
- oper = parse_operator (response->str);
- if (oper) {
- MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (serial);
+ if (error)
+ return;
- if (GPOINTER_TO_INT (user_data) == 0) {
- g_free (priv->oper_code);
- priv->oper_code = oper;
- } else {
- g_free (priv->oper_name);
- priv->oper_name = oper;
+ oper = parse_operator (response->str);
+ if (!oper)
+ return;
- mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (serial), priv->reg_status,
- priv->oper_code, priv->oper_name);
- }
- }
- }
+ g_free (priv->oper_code);
+ priv->oper_code = oper;
+}
+
+static void
+read_operator_name_done (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data);
+ char *oper;
+
+ if (error)
+ return;
+
+ oper = parse_operator (response->str);
+ if (!oper)
+ return;
+
+ g_free (priv->oper_name);
+ priv->oper_name = oper;
+
+ mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (user_data),
+ priv->reg_status,
+ priv->oper_code,
+ priv->oper_name);
}
/* Registration */
@@ -579,24 +763,27 @@ reg_status_updated (MMGenericGsm *self, int new_value)
}
static void
-reg_state_changed (MMSerial *serial,
+reg_state_changed (MMSerialPort *port,
GMatchInfo *match_info,
gpointer user_data)
{
+ MMGenericGsm *self = MM_GENERIC_GSM (user_data);
char *str;
str = g_match_info_fetch (match_info, 1);
- reg_status_updated (MM_GENERIC_GSM (serial), atoi (str));
+ reg_status_updated (self, atoi (str));
g_free (str);
}
static gboolean
reg_status_again (gpointer data)
{
+ MMGenericGsmPrivate *priv;
MMCallbackInfo *info = (MMCallbackInfo *) data;
- if (MM_GENERIC_GSM_GET_PRIVATE (info->modem)->pending_reg_id)
- get_registration_status (MM_SERIAL (info->modem), info);
+ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+ if (priv->pending_reg_id)
+ get_registration_status (priv->primary, info);
return FALSE;
}
@@ -608,13 +795,13 @@ reg_status_again_remove (gpointer data)
}
static void
-get_reg_status_done (MMSerial *serial,
+get_reg_status_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- MMGenericGsm *self = MM_GENERIC_GSM (serial);
+ MMGenericGsm *self = MM_GENERIC_GSM (info->modem);
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
int unsolicited, stat;
guint id;
@@ -637,7 +824,7 @@ get_reg_status_done (MMSerial *serial,
return;
}
- reg_status_updated (MM_GENERIC_GSM (serial), stat);
+ reg_status_updated (self, stat);
if (priv->pending_reg_id) {
/* Registration is still going */
@@ -673,19 +860,19 @@ get_reg_status_done (MMSerial *serial,
}
static void
-get_registration_status (MMSerial *serial, MMCallbackInfo *info)
+get_registration_status (MMSerialPort *port, MMCallbackInfo *info)
{
- mm_serial_queue_command (serial, "+CREG?", 3, get_reg_status_done, info);
+ mm_serial_port_queue_command (port, "+CREG?", 3, get_reg_status_done, info);
}
static void
-register_done (MMSerial *serial,
+register_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
/* Ignore errors here, get the actual registration status */
- get_registration_status (serial, (MMCallbackInfo *) user_data);
+ get_registration_status (port, (MMCallbackInfo *) user_data);
}
static gboolean
@@ -708,8 +895,8 @@ do_register (MMModemGsmNetwork *modem,
MMModemFn callback,
gpointer user_data)
{
- MMCallbackInfo *info;
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ MMCallbackInfo *info;
char *command;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
@@ -721,7 +908,7 @@ do_register (MMModemGsmNetwork *modem,
else
command = g_strdup ("+COPS=0,,");
- mm_serial_queue_command (MM_SERIAL (modem), command, 10, register_done, info);
+ mm_serial_port_queue_command (priv->primary, command, 10, register_done, info);
g_free (command);
}
@@ -755,7 +942,7 @@ get_registration_info (MMModemGsmNetwork *self,
}
static void
-connect_report_done (MMSerial *serial,
+connect_report_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -771,17 +958,19 @@ connect_report_done (MMSerial *serial,
}
static void
-connect_done (MMSerial *serial,
+connect_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv;
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
if (error) {
info->error = g_error_copy (error);
/* Try to get more information why it failed */
- mm_serial_queue_command (serial, "+CEER", 3, connect_report_done, info);
+ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+ mm_serial_port_queue_command (priv->primary, "+CEER", 3, connect_report_done, info);
} else
/* Done */
mm_callback_info_schedule (info);
@@ -793,6 +982,7 @@ connect (MMModem *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
char *command;
guint32 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (modem));
@@ -813,12 +1003,12 @@ connect (MMModem *modem,
} else
command = g_strconcat ("DT", number, NULL);
- mm_serial_queue_command (MM_SERIAL (modem), command, 60, connect_done, info);
+ mm_serial_port_queue_command (priv->primary, command, 60, connect_done, info);
g_free (command);
}
static void
-disconnect_flash_done (MMSerial *serial, gpointer user_data)
+disconnect_flash_done (MMSerialPort *port, gpointer user_data)
{
mm_callback_info_schedule ((MMCallbackInfo *) user_data);
}
@@ -828,13 +1018,14 @@ disconnect (MMModem *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
/* First, reset the previously used CID */
mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0);
info = mm_callback_info_new (modem, callback, user_data);
- mm_serial_flash (MM_SERIAL (modem), 1000, disconnect_flash_done, info);
+ mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info);
}
static void
@@ -858,7 +1049,7 @@ destroy_scan_data (gpointer data)
}
static void
-scan_done (MMSerial *serial,
+scan_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -868,17 +1059,27 @@ scan_done (MMSerial *serial,
if (error)
info->error = g_error_copy (error);
- else if (!strncmp (reply, "+COPS: ", 7)) {
+ else if (strstr (reply, "+COPS: ")) {
/* Got valid reply */
GPtrArray *results;
GRegex *r;
GMatchInfo *match_info;
GError *err = NULL;
- reply += 7;
+ reply = strstr (reply, "+COPS: ") + 7;
- /* Pattern without crazy escaping using | for matching: (|\d|,"|.+|","|.+|","|.+|",|\d|) */
- r = g_regex_new ("\\((\\d),\"(.*)\",\"(.*)\",\"(.*)\",(\\d)\\)", G_REGEX_UNGREEDY, 0, &err);
+ /* Pattern without crazy escaping using | for matching: (|\d|,"|.+|","|.+|","|.+|"\)?,|\d|) */
+
+ /* Quirk: Sony-Ericsson TM-506 sometimes includes a stray ')' like so:
+ *
+ * +COPS: (2,"","T-Mobile","31026",0),(1,"AT&T","AT&T","310410"),0)
+ *
+ * Quirk: Motorola C-series (BUSlink SCWi275u) don't include the operator
+ * number, like so:
+ *
+ * +COPS: (2,"T-Mobile","","310260"),(0,"Cingular Wireless","","310410")
+ */
+ r = g_regex_new ("\\((\\d),\"(.*)\",\"(.*)\",\"(.*)\"\\)?[,]?[(\\d)]?\\)", G_REGEX_UNGREEDY, 0, &err);
if (err) {
g_error ("Invalid regular expression: %s", err->message);
g_error_free (err);
@@ -919,6 +1120,7 @@ scan (MMModemGsmNetwork *modem,
MMModemGsmNetworkScanFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
info = mm_callback_info_new_full (MM_MODEM (modem),
@@ -926,13 +1128,13 @@ scan (MMModemGsmNetwork *modem,
G_CALLBACK (callback),
user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "+COPS=?", 60, scan_done, info);
+ mm_serial_port_queue_command (priv->primary, "+COPS=?", 60, scan_done, info);
}
/* SetApn */
static void
-set_apn_done (MMSerial *serial,
+set_apn_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -942,14 +1144,14 @@ set_apn_done (MMSerial *serial,
if (error)
info->error = g_error_copy (error);
else
- mm_generic_gsm_set_cid (MM_GENERIC_GSM (serial),
+ mm_generic_gsm_set_cid (MM_GENERIC_GSM (info->modem),
GPOINTER_TO_UINT (mm_callback_info_get_data (info, "cid")));
mm_callback_info_schedule (info);
}
static void
-cid_range_read (MMSerial *serial,
+cid_range_read (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1009,13 +1211,13 @@ cid_range_read (MMSerial *serial,
mm_callback_info_set_data (info, "cid", GUINT_TO_POINTER (cid), NULL);
command = g_strdup_printf ("+CGDCONT=%d, \"IP\", \"%s\"", cid, apn);
- mm_serial_queue_command (serial, command, 3, set_apn_done, info);
+ mm_serial_port_queue_command (port, command, 3, set_apn_done, info);
g_free (command);
}
}
static void
-existing_apns_read (MMSerial *serial,
+existing_apns_read (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1048,7 +1250,7 @@ existing_apns_read (MMSerial *serial,
apn = g_match_info_fetch (match_info, 3);
if (!strcmp (apn, new_apn)) {
- mm_generic_gsm_set_cid (MM_GENERIC_GSM (serial), (guint32) num_cid);
+ mm_generic_gsm_set_cid (MM_GENERIC_GSM (info->modem), (guint32) num_cid);
found = TRUE;
}
@@ -1080,7 +1282,7 @@ existing_apns_read (MMSerial *serial,
mm_callback_info_schedule (info);
else
/* APN not configured on the card. Get the allowed CID range */
- mm_serial_queue_command_cached (serial, "+CGDCONT=?", 3, cid_range_read, info);
+ mm_serial_port_queue_command_cached (port, "+CGDCONT=?", 3, cid_range_read, info);
}
static void
@@ -1089,23 +1291,25 @@ set_apn (MMModemGsmNetwork *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
mm_callback_info_set_data (info, "apn", g_strdup (apn), g_free);
/* Start by searching if the APN is already in card */
- mm_serial_queue_command (MM_SERIAL (modem), "+CGDCONT?", 3, existing_apns_read, info);
+ mm_serial_port_queue_command (priv->primary, "+CGDCONT?", 3, existing_apns_read, info);
}
/* GetSignalQuality */
static void
-get_signal_quality_done (MMSerial *serial,
+get_signal_quality_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv;
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *reply = response->str;
@@ -1124,7 +1328,8 @@ get_signal_quality_done (MMSerial *serial,
/* Normalize the quality */
quality = quality * 100 / 31;
- MM_GENERIC_GSM_GET_PRIVATE (serial)->signal_quality = quality;
+ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+ priv->signal_quality = quality;
mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
} else
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
@@ -1139,23 +1344,26 @@ get_signal_quality (MMModemGsmNetwork *modem,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMCallbackInfo *info;
+ gboolean connected;
- if (mm_serial_is_connected (MM_SERIAL (modem))) {
- g_message ("Returning saved signal quality %d", MM_GENERIC_GSM_GET_PRIVATE (modem)->signal_quality);
- callback (MM_MODEM (modem), MM_GENERIC_GSM_GET_PRIVATE (modem)->signal_quality, NULL, user_data);
+ connected = mm_serial_port_is_connected (priv->primary);
+ if (connected && !priv->secondary) {
+ g_message ("Returning saved signal quality %d", priv->signal_quality);
+ callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data);
return;
}
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "+CSQ", 3, get_signal_quality_done, info);
+ mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, "+CSQ", 3, get_signal_quality_done, info);
}
/*****************************************************************************/
/* MMModemGsmSms interface */
static void
-sms_send_done (MMSerial *serial,
+sms_send_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1178,19 +1386,51 @@ sms_send (MMModemGsmSms *modem,
MMModemFn callback,
gpointer user_data)
{
+ MMGenericGsmPrivate *priv;
MMCallbackInfo *info;
char *command;
+ gboolean connected;
+ MMSerialPort *port = NULL;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
+ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+ connected = mm_serial_port_is_connected (priv->primary);
+ if (connected)
+ port = priv->secondary;
+ else
+ port = priv->primary;
+
+ if (!port) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Cannot send SMS while connected");
+ mm_callback_info_schedule (info);
+ return;
+ }
+
/* FIXME: use the PDU mode instead */
- mm_serial_queue_command (MM_SERIAL (modem), "AT+CMGF=1", 3, NULL, NULL);
+ mm_serial_port_queue_command (port, "AT+CMGF=1", 3, NULL, NULL);
command = g_strdup_printf ("+CMGS=\"%s\"\r%s\x1a", number, text);
- mm_serial_queue_command (MM_SERIAL (modem), command, 10, sms_send_done, info);
+ mm_serial_port_queue_command (port, command, 10, sms_send_done, info);
g_free (command);
}
+MMSerialPort *
+mm_generic_gsm_get_port (MMGenericGsm *modem,
+ MMPortType ptype)
+{
+ g_return_val_if_fail (MM_IS_GENERIC_GSM (modem), NULL);
+ g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL);
+
+ if (ptype == MM_PORT_TYPE_PRIMARY)
+ return MM_GENERIC_GSM_GET_PRIVATE (modem)->primary;
+ else if (ptype == MM_PORT_TYPE_SECONDARY)
+ return MM_GENERIC_GSM_GET_PRIVATE (modem)->secondary;
+
+ return NULL;
+}
+
/*****************************************************************************/
/* MMModemSimple interface */
@@ -1438,9 +1678,13 @@ simple_get_status (MMModemSimple *simple,
static void
modem_init (MMModem *modem_class)
{
+ modem_class->owns_port = owns_port;
+ modem_class->grab_port = grab_port;
+ modem_class->release_port = release_port;
modem_class->enable = enable;
modem_class->connect = connect;
modem_class->disconnect = disconnect;
+ modem_class->get_info = get_card_info;
}
static void
@@ -1448,7 +1692,6 @@ modem_gsm_card_init (MMModemGsmCard *class)
{
class->get_imei = get_imei;
class->get_imsi = get_imsi;
- class->get_info = get_card_info;
class->send_pin = send_pin;
class->send_puk = send_puk;
class->enable_pin = enable_pin;
@@ -1481,16 +1724,6 @@ modem_simple_init (MMModemSimple *class)
static void
mm_generic_gsm_init (MMGenericGsm *self)
{
- GRegex *regex;
-
- mm_serial_set_response_parser (MM_SERIAL (self),
- mm_serial_parser_v1_parse,
- mm_serial_parser_v1_new (),
- mm_serial_parser_v1_destroy);
-
- regex = g_regex_new ("\\r\\n\\+CREG: (\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, reg_state_changed, NULL, NULL);
- g_regex_unref (regex);
}
static void
@@ -1504,16 +1737,23 @@ set_property (GObject *object, guint prop_id,
/* Construct only */
priv->driver = g_value_dup_string (value);
break;
- case MM_MODEM_PROP_DEVICE:
- g_free (priv->data_device);
- priv->data_device = g_value_dup_string (value);
+ case MM_MODEM_PROP_PLUGIN:
+ /* Construct only */
+ priv->plugin = g_value_dup_string (value);
break;
- case MM_MODEM_PROP_TYPE:
- priv->modem_type = g_value_get_uint (value);
+ case MM_MODEM_PROP_MASTER_DEVICE:
+ /* Constrcut only */
+ priv->device = g_value_dup_string (value);
break;
case MM_MODEM_PROP_IP_METHOD:
priv->ip_method = g_value_get_uint (value);
break;
+ case MM_MODEM_PROP_TYPE:
+ case MM_MODEM_PROP_VALID:
+ case MM_GENERIC_GSM_PROP_POWER_UP_CMD:
+ case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
+ case MM_GENERIC_GSM_PROP_INIT_CMD:
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1527,21 +1767,39 @@ get_property (GObject *object, guint prop_id,
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (object);
switch (prop_id) {
- case MM_MODEM_PROP_DEVICE:
- if (priv->data_device)
- g_value_set_string (value, priv->data_device);
+ case MM_MODEM_PROP_DATA_DEVICE:
+ if (priv->data)
+ g_value_set_string (value, mm_port_get_device (priv->data));
else
- g_value_set_string (value, mm_serial_get_device (MM_SERIAL (object)));
+ g_value_set_string (value, NULL);
+ break;
+ case MM_MODEM_PROP_MASTER_DEVICE:
+ g_value_set_string (value, priv->device);
break;
case MM_MODEM_PROP_DRIVER:
- g_value_set_string (value, MM_GENERIC_GSM_GET_PRIVATE (object)->driver);
+ g_value_set_string (value, priv->driver);
+ break;
+ case MM_MODEM_PROP_PLUGIN:
+ g_value_set_string (value, priv->plugin);
break;
case MM_MODEM_PROP_TYPE:
- g_value_set_uint (value, priv->modem_type);
+ g_value_set_uint (value, MM_MODEM_TYPE_GSM);
break;
case MM_MODEM_PROP_IP_METHOD:
g_value_set_uint (value, priv->ip_method);
break;
+ case MM_MODEM_PROP_VALID:
+ g_value_set_boolean (value, priv->valid);
+ break;
+ case MM_GENERIC_GSM_PROP_POWER_UP_CMD:
+ g_value_set_string (value, "+CFUN=1");
+ break;
+ case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
+ g_value_set_string (value, "+CFUN=0");
+ break;
+ case MM_GENERIC_GSM_PROP_INIT_CMD:
+ g_value_set_string (value, "Z E0 V1 X4 &C1 +CMEE=1");
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1578,14 +1836,22 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass)
/* Properties */
g_object_class_override_property (object_class,
- MM_MODEM_PROP_DEVICE,
- MM_MODEM_DEVICE);
+ MM_MODEM_PROP_DATA_DEVICE,
+ MM_MODEM_DATA_DEVICE);
+
+ g_object_class_override_property (object_class,
+ MM_MODEM_PROP_MASTER_DEVICE,
+ MM_MODEM_MASTER_DEVICE);
g_object_class_override_property (object_class,
MM_MODEM_PROP_DRIVER,
MM_MODEM_DRIVER);
g_object_class_override_property (object_class,
+ MM_MODEM_PROP_PLUGIN,
+ MM_MODEM_PLUGIN);
+
+ g_object_class_override_property (object_class,
MM_MODEM_PROP_TYPE,
MM_MODEM_TYPE);
@@ -1593,6 +1859,33 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass)
MM_MODEM_PROP_IP_METHOD,
MM_MODEM_IP_METHOD);
+ g_object_class_override_property (object_class,
+ MM_MODEM_PROP_VALID,
+ MM_MODEM_VALID);
+
+ g_object_class_install_property
+ (object_class, MM_GENERIC_GSM_PROP_POWER_UP_CMD,
+ g_param_spec_string (MM_GENERIC_GSM_POWER_UP_CMD,
+ "PowerUpCommand",
+ "Power up command",
+ "+CFUN=1",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, MM_GENERIC_GSM_PROP_POWER_DOWN_CMD,
+ g_param_spec_string (MM_GENERIC_GSM_POWER_DOWN_CMD,
+ "PowerDownCommand",
+ "Power down command",
+ "+CFUN=0",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, MM_GENERIC_GSM_PROP_INIT_CMD,
+ g_param_spec_string (MM_GENERIC_GSM_INIT_CMD,
+ "InitCommand",
+ "Initialization command",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
GType
@@ -1633,7 +1926,10 @@ mm_generic_gsm_get_type (void)
(GInterfaceInitFunc) modem_simple_init
};
- generic_gsm_type = g_type_register_static (MM_TYPE_SERIAL, "MMGenericGsm", &generic_gsm_type_info, 0);
+ generic_gsm_type = g_type_register_static (MM_TYPE_MODEM_BASE,
+ "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);
diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h
index 3f857365..bd0af4ba 100644
--- a/src/mm-generic-gsm.h
+++ b/src/mm-generic-gsm.h
@@ -4,27 +4,44 @@
#define MM_GENERIC_GSM_H
#include "mm-modem-gsm-network.h"
-#include "mm-serial.h"
+#include "mm-modem-base.h"
+#include "mm-serial-port.h"
+
+#define MM_TYPE_GENERIC_GSM (mm_generic_gsm_get_type ())
+#define MM_GENERIC_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_GENERIC_GSM, MMGenericGsm))
+#define MM_GENERIC_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_GENERIC_GSM, MMGenericGsmClass))
+#define MM_IS_GENERIC_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_GENERIC_GSM))
+#define MM_IS_GENERIC_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_GENERIC_GSM))
+#define MM_GENERIC_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_GENERIC_GSM, MMGenericGsmClass))
+
+#define MM_GENERIC_GSM_POWER_UP_CMD "power-up-cmd"
+#define MM_GENERIC_GSM_POWER_DOWN_CMD "power-down-cmd"
+#define MM_GENERIC_GSM_INIT_CMD "init-cmd"
+
+typedef enum {
+ MM_GENERIC_GSM_PROP_FIRST = 0x2000,
+
+ MM_GENERIC_GSM_PROP_POWER_UP_CMD,
+ MM_GENERIC_GSM_PROP_POWER_DOWN_CMD,
+ MM_GENERIC_GSM_PROP_INIT_CMD,
+
+ MM_GENERIC_GSM_LAST_PROP = MM_GENERIC_GSM_PROP_POWER_DOWN_CMD
+} MMGenericGsmProp;
-#define MM_TYPE_GENERIC_GSM (mm_generic_gsm_get_type ())
-#define MM_GENERIC_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_GENERIC_GSM, MMGenericGsm))
-#define MM_GENERIC_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_GENERIC_GSM, MMGenericGsmClass))
-#define MM_IS_GENERIC_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_GENERIC_GSM))
-#define MM_IS_GENERIC_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_GENERIC_GSM))
-#define MM_GENERIC_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_GENERIC_GSM, MMGenericGsmClass))
typedef struct {
- MMSerial parent;
+ MMModemBase parent;
} MMGenericGsm;
typedef struct {
- MMSerialClass parent;
+ MMModemBaseClass parent;
} MMGenericGsmClass;
GType mm_generic_gsm_get_type (void);
-MMModem *mm_generic_gsm_new (const char *serial_device,
- const char *driver);
+MMModem *mm_generic_gsm_new (const char *device,
+ const char *driver,
+ const char *plugin);
void mm_generic_gsm_set_unsolicited_registration (MMGenericGsm *modem,
gboolean enabled);
@@ -42,4 +59,13 @@ void mm_generic_gsm_check_pin (MMGenericGsm *modem,
MMModemFn callback,
gpointer user_data);
+MMSerialPort *mm_generic_gsm_get_port (MMGenericGsm *modem,
+ MMPortType ptype);
+
+MMPort *mm_generic_gsm_grab_port (MMGenericGsm *modem,
+ const char *subsys,
+ const char *name,
+ MMPortType ptype,
+ GError **error);
+
#endif /* MM_GENERIC_GSM_H */
diff --git a/src/mm-manager.c b/src/mm-manager.c
index a19c9446..aa109a99 100644
--- a/src/mm-manager.c
+++ b/src/mm-manager.c
@@ -2,12 +2,12 @@
#include <string.h>
#include <gmodule.h>
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "mm-manager.h"
#include "mm-errors.h"
-#include "mm-generic-gsm.h"
-#include "mm-generic-cdma.h"
#include "mm-plugin.h"
static gboolean impl_manager_enumerate_devices (MMManager *manager,
@@ -29,11 +29,15 @@ static guint signals[LAST_SIGNAL] = { 0 };
#define MM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MANAGER, MMManagerPrivate))
+#define DBUS_PATH_TAG "dbus-path"
+
typedef struct {
DBusGConnection *connection;
- LibHalContext *hal_ctx;
+ GUdevClient *udev;
GSList *plugins;
GHashTable *modems;
+
+ GHashTable *supports;
} MMManagerPrivate;
static MMPlugin *
@@ -97,6 +101,7 @@ load_plugins (MMManager *manager)
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
GDir *dir;
const char *fname;
+ MMPlugin *generic_plugin = NULL;
if (!g_module_supported ()) {
g_warning ("GModules are not supported on your platform!");
@@ -120,10 +125,18 @@ load_plugins (MMManager *manager)
plugin = load_plugin (path);
g_free (path);
- if (plugin)
- priv->plugins = g_slist_append (priv->plugins, plugin);
+ if (plugin) {
+ if (!strcmp (mm_plugin_get_name (plugin), MM_PLUGIN_GENERIC_NAME))
+ generic_plugin = plugin;
+ else
+ priv->plugins = g_slist_append (priv->plugins, plugin);
+ }
}
+ /* Make sure the generic plugin is last */
+ if (generic_plugin)
+ priv->plugins = g_slist_append (priv->plugins, generic_plugin);
+
g_dir_close (dir);
}
@@ -138,7 +151,7 @@ mm_manager_new (DBusGConnection *bus)
if (manager) {
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
- priv->connection = bus;
+ priv->connection = dbus_g_connection_ref (bus);
dbus_g_connection_register_g_object (priv->connection,
MM_DBUS_PATH,
G_OBJECT (manager));
@@ -147,296 +160,441 @@ mm_manager_new (DBusGConnection *bus)
return manager;
}
-static char *
-get_driver_name (LibHalContext *ctx, const char *udi)
+static void
+remove_modem (MMManager *manager, MMModem *modem)
{
- char *parent_udi;
- char *driver = NULL;
+ MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
+ char *device;
- parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
- if (parent_udi) {
- driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
- libhal_free_string (parent_udi);
- }
+ device = mm_modem_get_device (modem);
+ g_assert (device);
+ g_debug ("Removed modem %s", device);
- return driver;
+ g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
+ g_hash_table_remove (priv->modems, device);
+ g_free (device);
}
-static MMModem *
-create_generic_modem (MMManager *manager, const char *udi)
+static void
+modem_valid (MMModem *modem, GParamSpec *pspec, gpointer user_data)
{
+ MMManager *manager = MM_MANAGER (user_data);
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
- MMModem *modem;
- char **capabilities;
- char **iter;
- char *serial_device;
- char *driver;
- gboolean type_gsm = FALSE;
- gboolean type_cdma = FALSE;
-
- capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "modem.command_sets", NULL);
- for (iter = capabilities; iter && *iter; iter++) {
- if (!strcmp (*iter, "GSM-07.07")) {
- type_gsm = TRUE;
- break;
- }
- if (!strcmp (*iter, "IS-707-A")) {
- type_cdma = TRUE;
- break;
- }
- }
- g_strfreev (capabilities);
-
- if (!type_gsm && !type_cdma)
- return NULL;
+ static guint32 id = 0;
+ char *path, *device;
- serial_device = libhal_device_get_property_string (priv->hal_ctx, udi, "serial.device", NULL);
- g_return_val_if_fail (serial_device != NULL, NULL);
+ if (mm_modem_get_valid (modem)) {
+ path = g_strdup_printf (MM_DBUS_PATH"/Modems/%d", id++);
+ dbus_g_connection_register_g_object (priv->connection, path, G_OBJECT (modem));
+ g_object_set_data_full (G_OBJECT (modem), DBUS_PATH_TAG, path, (GDestroyNotify) g_free);
- driver = get_driver_name (priv->hal_ctx, udi);
- g_return_val_if_fail (driver != NULL, NULL);
+ device = mm_modem_get_device (modem);
+ g_assert (device);
+ g_debug ("Exported modem %s as %s", device, path);
+ g_free (device);
- if (type_gsm)
- modem = mm_generic_gsm_new (serial_device, driver);
- else
- modem = mm_generic_cdma_new (serial_device, driver);
-
- g_free (serial_device);
- g_free (driver);
-
- if (modem)
- g_debug ("Created new generic modem (%s)", udi);
- else
- g_warning ("Failed to create generic modem (%s)", udi);
-
- return modem;
+ g_signal_emit (manager, signals[DEVICE_ADDED], 0, modem);
+ } else
+ remove_modem (manager, modem);
}
static void
-add_modem (MMManager *manager, const char *udi, MMModem *modem)
+add_modem (MMManager *manager, MMModem *modem)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
+ char *device;
+ gboolean valid = FALSE;
+
+ device = mm_modem_get_device (modem);
+ g_assert (device);
+ if (!g_hash_table_lookup (priv->modems, device)) {
+ g_hash_table_insert (priv->modems, g_strdup (device), modem);
+ g_debug ("Added modem %s", device);
+ g_signal_connect (modem, "notify::valid", G_CALLBACK (modem_valid), manager);
+ g_object_get (modem, MM_MODEM_VALID, &valid, NULL);
+ if (valid)
+ modem_valid (modem, NULL, manager);
+ }
+ g_free (device);
+}
- g_hash_table_insert (priv->modems, g_strdup (udi), modem);
- dbus_g_connection_register_g_object (priv->connection, udi, G_OBJECT (modem));
-
- g_signal_emit (manager, signals[DEVICE_ADDED], 0, modem);
+static void
+enumerate_devices_cb (gpointer key, gpointer val, gpointer user_data)
+{
+ MMModem *modem = MM_MODEM (val);
+ GPtrArray **devices = (GPtrArray **) user_data;
+ const char *path;
+ gboolean valid = FALSE;
+
+ g_object_get (G_OBJECT (modem), MM_MODEM_VALID, &valid, NULL);
+ if (valid) {
+ path = g_object_get_data (G_OBJECT (modem), DBUS_PATH_TAG);
+ g_return_if_fail (path != NULL);
+ g_ptr_array_add (*devices, g_strdup (path));
+ }
}
-static MMModem *
-modem_exists (MMManager *manager, const char *udi)
+static gboolean
+impl_manager_enumerate_devices (MMManager *manager,
+ GPtrArray **devices,
+ GError **err)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
- return (MMModem *) g_hash_table_lookup (priv->modems, udi);
+ *devices = g_ptr_array_sized_new (g_hash_table_size (priv->modems));
+ g_hash_table_foreach (priv->modems, enumerate_devices_cb, devices);
+
+ return TRUE;
}
-static void
-create_initial_modems_from_plugins (MMManager *manager)
+static MMModem *
+find_modem_for_port (MMManager *manager, const char *subsys, const char *name)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
- GSList *iter;
+ GHashTableIter iter;
+ gpointer key, value;
- for (iter = priv->plugins; iter; iter = iter->next) {
- MMPlugin *plugin = MM_PLUGIN (iter->data);
- char **udis;
- int i;
+ g_hash_table_iter_init (&iter, priv->modems);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ MMModem *modem = MM_MODEM (value);
- udis = mm_plugin_list_supported_udis (plugin, priv->hal_ctx);
- if (udis) {
- for (i = 0; udis[i]; i++) {
- char *udi = udis[i];
- MMModem *modem;
+ if (mm_modem_owns_port (modem, subsys, name))
+ return modem;
+ }
+ return NULL;
+}
- if (modem_exists (manager, udi)) {
- g_warning ("Modem for UDI %s already exists, ignoring", udi);
- continue;
- }
+typedef struct {
+ MMManager *manager;
+ char *subsys;
+ char *name;
+ GSList *plugins;
+ GSList *cur_plugin;
+ guint defer_id;
+ guint done_id;
- modem = mm_plugin_create_modem (plugin, priv->hal_ctx, udi);
- if (modem)
- add_modem (manager, udi, modem);
- }
+ guint32 best_level;
+ MMPlugin *best_plugin;
+} SupportsInfo;
- g_strfreev (udis);
- }
- }
+static SupportsInfo *
+supports_info_new (MMManager *self, const char *subsys, const char *name)
+{
+ MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (self);
+ SupportsInfo *info;
+
+ info = g_malloc0 (sizeof (SupportsInfo));
+ info->manager = self;
+ info->subsys = g_strdup (subsys);
+ info->name = g_strdup (name);
+ info->plugins = g_slist_copy (priv->plugins);
+ info->cur_plugin = info->plugins;
+ return info;
}
static void
-create_initial_modems_generic (MMManager *manager)
+supports_info_free (SupportsInfo *info)
{
- MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
- char **devices;
- int num_devices;
- int i;
- DBusError err;
-
- dbus_error_init (&err);
- devices = libhal_find_device_by_capability (priv->hal_ctx, "modem", &num_devices, &err);
- if (dbus_error_is_set (&err)) {
- g_warning ("Could not list HAL devices: %s", err.message);
- dbus_error_free (&err);
- }
+ /* Cancel any in-process operation on the first plugin */
+ if (info->cur_plugin)
+ mm_plugin_cancel_supports_port (MM_PLUGIN (info->cur_plugin->data), info->subsys, info->name);
- if (devices) {
- for (i = 0; i < num_devices; i++) {
- char *udi = devices[i];
- MMModem *modem;
+ if (info->defer_id)
+ g_source_remove (info->defer_id);
- if (modem_exists (manager, udi))
- /* Already exists, most likely handled by a plugin */
- continue;
+ if (info->done_id)
+ g_source_remove (info->done_id);
- modem = create_generic_modem (manager, udi);
- if (modem)
- add_modem (manager, g_strdup (udi), modem);
- }
- }
+ g_free (info->subsys);
+ g_free (info->name);
+ g_slist_free (info->plugins);
+ memset (info, 0, sizeof (SupportsInfo));
+ g_free (info);
+}
- g_strfreev (devices);
+static char *
+get_key (const char *subsys, const char *name)
+{
+ return g_strdup_printf ("%s%s", subsys, name);
}
-static void
-create_initial_modems (MMManager *manager)
+
+static void supports_callback (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ guint32 level,
+ gpointer user_data);
+
+static void try_supports_port (MMManager *manager,
+ MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ SupportsInfo *info);
+
+static gboolean
+supports_defer_timeout (gpointer user_data)
{
- create_initial_modems_from_plugins (manager);
- create_initial_modems_generic (manager);
+ SupportsInfo *info = user_data;
+
+ g_debug ("(%s): re-checking support...", info->name);
+ try_supports_port (info->manager,
+ MM_PLUGIN (info->cur_plugin->data),
+ info->subsys,
+ info->name,
+ info);
+ return FALSE;
}
static void
-enumerate_devices_cb (gpointer key, gpointer val, gpointer user_data)
+try_supports_port (MMManager *manager,
+ MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ SupportsInfo *info)
{
- GPtrArray **devices = (GPtrArray **) user_data;
-
- g_ptr_array_add (*devices, g_strdup ((char *) key));
+ MMPluginSupportsResult result;
+
+ result = mm_plugin_supports_port (plugin, subsys, name, supports_callback, info);
+
+ switch (result) {
+ case MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED:
+ /* If the plugin knows it doesn't support the modem, just call the
+ * callback and indicate 0 support.
+ */
+ supports_callback (plugin, subsys, name, 0, info);
+ break;
+ case MM_PLUGIN_SUPPORTS_PORT_DEFER:
+ g_debug ("(%s): (%s) deferring support check", mm_plugin_get_name (plugin), name);
+ if (info->defer_id)
+ g_source_remove (info->defer_id);
+
+ /* defer port detection for a bit as requested by the plugin */
+ info->defer_id = g_timeout_add (3000, supports_defer_timeout, info);
+ break;
+ case MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS:
+ default:
+ break;
+ }
}
static gboolean
-impl_manager_enumerate_devices (MMManager *manager,
- GPtrArray **devices,
- GError **err)
+do_grab_port (gpointer user_data)
{
- MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
+ SupportsInfo *info = user_data;
+ MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (info->manager);
+ MMModem *modem;
+ GError *error = NULL;
+ char *key;
+ GSList *iter;
- *devices = g_ptr_array_sized_new (g_hash_table_size (priv->modems));
- g_hash_table_foreach (priv->modems, enumerate_devices_cb, devices);
+ /* No more plugins to try */
+ if (info->best_plugin) {
+ /* Create the modem */
+ modem = mm_plugin_grab_port (info->best_plugin, info->subsys, info->name, &error);
+ if (modem) {
+ guint32 modem_type = MM_MODEM_TYPE_UNKNOWN;
+ const char *type_name = "UNKNOWN";
+
+ g_object_get (G_OBJECT (modem), MM_MODEM_TYPE, &modem_type, NULL);
+ if (modem_type == MM_MODEM_TYPE_GSM)
+ type_name = "GSM";
+ else if (modem_type == MM_MODEM_TYPE_CDMA)
+ type_name = "CDMA";
+
+ g_message ("(%s): %s modem %s claimed port %s",
+ mm_plugin_get_name (info->best_plugin),
+ type_name,
+ mm_modem_get_device (modem),
+ info->name);
+
+ add_modem (info->manager, modem);
+ } else {
+ g_warning ("%s: plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
+ __func__,
+ mm_plugin_get_name (info->best_plugin),
+ info->subsys,
+ info->name,
+ error ? error->code : -1,
+ (error && error->message) ? error->message : "(unknown)");
+ }
+ }
- return TRUE;
+ /* Tell each plugin to clean up any outstanding supports task */
+ for (iter = info->plugins; iter; iter = g_slist_next (iter))
+ mm_plugin_cancel_supports_port (MM_PLUGIN (iter->data), info->subsys, info->name);
+ g_slist_free (info->plugins);
+ info->cur_plugin = info->plugins = NULL;
+
+ key = get_key (info->subsys, info->name);
+ g_hash_table_remove (priv->supports, key);
+ g_free (key);
+
+ return FALSE;
}
static void
-device_added (LibHalContext *ctx, const char *udi)
+supports_callback (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ guint32 level,
+ gpointer user_data)
+{
+ SupportsInfo *info = user_data;
+ MMPlugin *next_plugin = NULL;
+
+ info->cur_plugin = info->cur_plugin->next;
+ if (info->cur_plugin)
+ next_plugin = MM_PLUGIN (info->cur_plugin->data);
+
+ /* Is this plugin's result better than any one we've tried before? */
+ if (level > info->best_level) {
+ info->best_level = level;
+ info->best_plugin = plugin;
+ }
+
+ /* Prevent the generic plugin from probing devices that are already supported
+ * by other plugins. For Huawei for example, secondary ports shouldn't
+ * be probed, but the generic plugin would happily do so if allowed to.
+ */
+ if ( next_plugin
+ && !strcmp (mm_plugin_get_name (next_plugin), MM_PLUGIN_GENERIC_NAME)
+ && info->best_plugin)
+ next_plugin = NULL;
+
+ if (next_plugin) {
+ /* Try the next plugin */
+ try_supports_port (info->manager, next_plugin, info->subsys, info->name, info);
+ } else {
+ /* All done; let the best modem grab the port */
+ info->done_id = g_idle_add (do_grab_port, info);
+ }
+}
+
+static void
+device_added (MMManager *manager, GUdevDevice *device)
{
- MMManager *manager = MM_MANAGER (libhal_ctx_get_user_data (ctx));
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
- GSList *iter;
- MMModem *modem = NULL;
+ const char *subsys, *name;
+ SupportsInfo *info;
+ char *key;
+ gboolean found;
+
+ g_return_if_fail (device != NULL);
- if (modem_exists (manager, udi))
- /* Shouldn't happen */
+ if (!g_slist_length (priv->plugins))
return;
- for (iter = priv->plugins; iter && modem == NULL; iter = iter->next) {
- MMPlugin *plugin = MM_PLUGIN (iter->data);
+ subsys = g_udev_device_get_subsystem (device);
+ name = g_udev_device_get_name (device);
- if (mm_plugin_supports_udi (plugin, ctx, udi)) {
- modem = mm_plugin_create_modem (plugin, ctx, udi);
- if (modem)
- break;
- }
+ if (find_modem_for_port (manager, subsys, name))
+ return;
+
+ key = get_key (subsys, name);
+ found = !!g_hash_table_lookup (priv->supports, key);
+ if (found) {
+ g_free (key);
+ return;
}
- if (!modem)
- /* None of the plugins supported the udi, try generic devices */
- modem = create_generic_modem (manager, udi);
+ info = supports_info_new (manager, subsys, name);
+ g_hash_table_insert (priv->supports, key, info);
- if (modem)
- add_modem (manager, udi, modem);
+ try_supports_port (manager, MM_PLUGIN (info->cur_plugin->data), subsys, name, info);
}
static void
-device_removed (LibHalContext *ctx, const char *udi)
+device_removed (MMManager *manager, GUdevDevice *device)
{
- MMManager *manager = MM_MANAGER (libhal_ctx_get_user_data (ctx));
+ MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
MMModem *modem;
+ const char *subsys, *name;
+ char *key;
+ SupportsInfo *info;
+
+ g_return_if_fail (device != NULL);
+
+ if (!g_slist_length (priv->plugins))
+ return;
- modem = modem_exists (manager, udi);
+ subsys = g_udev_device_get_subsystem (device);
+ name = g_udev_device_get_name (device);
+ modem = find_modem_for_port (manager, subsys, name);
if (modem) {
- g_debug ("Removed modem %s", udi);
- g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
- g_hash_table_remove (MM_MANAGER_GET_PRIVATE (manager)->modems, udi);
+ mm_modem_release_port (modem, subsys, name);
+ return;
}
-}
-static void
-device_new_capability (LibHalContext *ctx, const char *udi, const char *capability)
-{
- device_added (ctx, udi);
-}
+ /* Maybe a plugin is checking whether or not the port is supported */
+ key = get_key (subsys, name);
+ info = g_hash_table_lookup (priv->supports, key);
+ if (info) {
+ if (info->plugins)
+ mm_plugin_cancel_supports_port (MM_PLUGIN (info->plugins->data), subsys, name);
+ g_hash_table_remove (priv->supports, key);
+ }
-DBusGConnection *
-mm_manager_get_bus (MMManager *manager)
-{
- g_return_val_if_fail (MM_IS_MANAGER (manager), NULL);
-
- return MM_MANAGER_GET_PRIVATE (manager)->connection;
+ g_free (key);
}
-static gboolean
-remove_one (gpointer key,
- gpointer value,
- gpointer user_data)
+static void
+handle_uevent (GUdevClient *client,
+ const char *action,
+ GUdevDevice *device,
+ gpointer user_data)
{
- const char *udi = (char *) key;
- MMModem *modem = MM_MODEM (value);
- MMManager *manager = MM_MANAGER (user_data);
+ MMManager *self = MM_MANAGER (user_data);
+ const char *subsys;
- g_debug ("Removed modem %s", udi);
- g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
+ g_return_if_fail (action != NULL);
- return TRUE;
+ /* A bit paranoid */
+ subsys = g_udev_device_get_subsystem (device);
+ g_return_if_fail (subsys != NULL);
+
+ g_return_if_fail (!strcmp (subsys, "tty") || !strcmp (subsys, "net"));
+
+ if (!strcmp (action, "add"))
+ device_added (self, device);
+ else if (!strcmp (action, "remove"))
+ device_removed (self, device);
}
void
-mm_manager_set_hal_ctx (MMManager *manager,
- LibHalContext *hal_ctx)
+mm_manager_start (MMManager *manager)
{
MMManagerPrivate *priv;
+ GList *devices, *iter;
+ g_return_if_fail (manager != NULL);
g_return_if_fail (MM_IS_MANAGER (manager));
priv = MM_MANAGER_GET_PRIVATE (manager);
- priv->hal_ctx = hal_ctx;
- if (hal_ctx) {
- libhal_ctx_set_user_data (hal_ctx, manager);
- libhal_ctx_set_device_added (hal_ctx, device_added);
- libhal_ctx_set_device_removed (hal_ctx, device_removed);
- libhal_ctx_set_device_new_capability (hal_ctx, device_new_capability);
+ devices = g_udev_client_query_by_subsystem (priv->udev, "tty");
+ for (iter = devices; iter; iter = g_list_next (iter))
+ device_added (manager, G_UDEV_DEVICE (iter->data));
- create_initial_modems (manager);
- } else {
- g_hash_table_foreach_remove (priv->modems, remove_one, manager);
- }
-}
-
-LibHalContext *
-mm_manager_get_hal_ctx (MMManager *manager)
-{
- g_return_val_if_fail (MM_IS_MANAGER (manager), NULL);
-
- return MM_MANAGER_GET_PRIVATE (manager)->hal_ctx;
+ devices = g_udev_client_query_by_subsystem (priv->udev, "net");
+ for (iter = devices; iter; iter = g_list_next (iter))
+ device_added (manager, G_UDEV_DEVICE (iter->data));
}
static void
mm_manager_init (MMManager *manager)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
+ const char *subsys[3] = { "tty", "net", NULL };
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
load_plugins (manager);
+
+ priv->supports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) supports_info_free);
+
+ priv->udev = g_udev_client_new (subsys);
+ g_assert (priv->udev);
+ g_signal_connect (priv->udev, "uevent", G_CALLBACK (handle_uevent), manager);
}
static void
@@ -444,16 +602,14 @@ finalize (GObject *object)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (object);
+ g_hash_table_destroy (priv->supports);
g_hash_table_destroy (priv->modems);
g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL);
g_slist_free (priv->plugins);
- if (priv->hal_ctx) {
- mm_manager_set_hal_ctx (MM_MANAGER (object), NULL);
- libhal_ctx_shutdown (priv->hal_ctx, NULL);
- libhal_ctx_free (priv->hal_ctx);
- }
+ if (priv->udev)
+ g_object_unref (priv->udev);
if (priv->connection)
dbus_g_connection_unref (priv->connection);
@@ -500,3 +656,4 @@ mm_manager_class_init (MMManagerClass *manager_class)
dbus_g_error_domain_register (MM_MODEM_CONNECT_ERROR, "org.freedesktop.ModemManager.Modem", MM_TYPE_MODEM_CONNECT_ERROR);
dbus_g_error_domain_register (MM_MOBILE_ERROR, "org.freedesktop.ModemManager.Modem.Gsm", MM_TYPE_MOBILE_ERROR);
}
+
diff --git a/src/mm-manager.h b/src/mm-manager.h
index 4426d0f1..0e7564ff 100644
--- a/src/mm-manager.h
+++ b/src/mm-manager.h
@@ -6,7 +6,6 @@
#include <glib/gtypes.h>
#include <glib-object.h>
#include <dbus/dbus-glib.h>
-#include <libhal.h>
#include "mm-modem.h"
#define MM_TYPE_MANAGER (mm_manager_get_type ())
@@ -34,10 +33,7 @@ typedef struct {
GType mm_manager_get_type (void);
MMManager *mm_manager_new (DBusGConnection *bus);
-DBusGConnection *mm_manager_get_bus (MMManager *manager);
-void mm_manager_set_hal_ctx (MMManager *manager,
- LibHalContext *hal_ctx);
-LibHalContext *mm_manager_get_hal_ctx (MMManager *manager);
+void mm_manager_start (MMManager *manager);
#endif /* MM_MANAGER_H */
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
new file mode 100644
index 00000000..30de1123
--- /dev/null
+++ b/src/mm-modem-base.c
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "mm-modem-base.h"
+#include "mm-serial-port.h"
+#include "mm-errors.h"
+#include "mm-options.h"
+
+G_DEFINE_TYPE (MMModemBase, mm_modem_base, G_TYPE_OBJECT)
+
+#define MM_MODEM_BASE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_BASE, MMModemBasePrivate))
+
+typedef struct {
+ GHashTable *ports;
+} MMModemBasePrivate;
+
+static char *
+get_hash_key (const char *subsys, const char *name)
+{
+ return g_strdup_printf ("%s%s", subsys, name);
+}
+
+MMPort *
+mm_modem_base_get_port (MMModemBase *self,
+ const char *subsys,
+ const char *name)
+{
+ MMPort *port;
+ char *key;
+
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (subsys != NULL, NULL);
+
+ g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), NULL);
+
+ key = get_hash_key (subsys, name);
+ port = g_hash_table_lookup (MM_MODEM_BASE_GET_PRIVATE (self)->ports, key);
+ g_free (key);
+ return port;
+}
+
+static void
+find_primary (gpointer key, gpointer data, gpointer user_data)
+{
+ MMPort **found = user_data;
+ MMPort *port = MM_PORT (data);
+
+ if (!*found && (mm_port_get_port_type (port) == MM_PORT_TYPE_PRIMARY))
+ *found = port;
+}
+
+MMPort *
+mm_modem_base_add_port (MMModemBase *self,
+ const char *subsys,
+ const char *name,
+ MMPortType ptype)
+{
+ MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
+ MMPort *port = NULL;
+ char *key;
+
+ g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL);
+ g_return_val_if_fail (subsys != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL);
+
+ g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), NULL);
+
+ key = get_hash_key (subsys, name);
+ port = g_hash_table_lookup (priv->ports, key);
+ g_free (key);
+ g_return_val_if_fail (port == NULL, NULL);
+
+ if (ptype == MM_PORT_TYPE_PRIMARY) {
+ g_hash_table_foreach (priv->ports, find_primary, &port);
+ 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")) {
+ port = MM_PORT (g_object_new (MM_TYPE_PORT,
+ MM_PORT_DEVICE, name,
+ MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET,
+ MM_PORT_TYPE, ptype,
+ NULL));
+ }
+
+ if (!port)
+ return NULL;
+
+ key = get_hash_key (subsys, name);
+ g_hash_table_insert (priv->ports, key, port);
+ return port;
+}
+
+gboolean
+mm_modem_base_remove_port (MMModemBase *self, MMPort *port)
+{
+ g_return_val_if_fail (MM_IS_MODEM_BASE (self), FALSE);
+ g_return_val_if_fail (port != NULL, FALSE);
+
+ return g_hash_table_remove (MM_MODEM_BASE_GET_PRIVATE (self)->ports, port);
+}
+
+/*****************************************************************************/
+
+static void
+mm_modem_base_init (MMModemBase *self)
+{
+ MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
+
+ priv->ports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+}
+
+static void
+finalize (GObject *object)
+{
+ MMModemBase *self = MM_MODEM_BASE (object);
+ MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
+
+ g_hash_table_destroy (priv->ports);
+
+ G_OBJECT_CLASS (mm_modem_base_parent_class)->finalize (object);
+}
+
+static void
+mm_modem_base_class_init (MMModemBaseClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMModemBasePrivate));
+
+ /* Virtual methods */
+ object_class->finalize = finalize;
+}
diff --git a/src/mm-modem-base.h b/src/mm-modem-base.h
new file mode 100644
index 00000000..9cb0df38
--- /dev/null
+++ b/src/mm-modem-base.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_MODEM_BASE_H
+#define MM_MODEM_BASE_H
+
+#include <glib.h>
+#include <glib/gtypes.h>
+#include <glib-object.h>
+
+#include "mm-port.h"
+
+#define MM_TYPE_MODEM_BASE (mm_modem_base_get_type ())
+#define MM_MODEM_BASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_BASE, MMModemBase))
+#define MM_MODEM_BASE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_BASE, MMModemBaseClass))
+#define MM_IS_MODEM_BASE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_BASE))
+#define MM_IS_MODEM_BASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_BASE))
+#define MM_MODEM_BASE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_BASE, MMModemBaseClass))
+
+typedef struct _MMModemBase MMModemBase;
+typedef struct _MMModemBaseClass MMModemBaseClass;
+
+struct _MMModemBase {
+ GObject parent;
+};
+
+struct _MMModemBaseClass {
+ GObjectClass parent;
+};
+
+GType mm_modem_base_get_type (void);
+
+MMPort *mm_modem_base_get_port (MMModemBase *self,
+ const char *subsys,
+ const char *name);
+
+MMPort *mm_modem_base_add_port (MMModemBase *self,
+ const char *subsys,
+ const char *name,
+ MMPortType ptype);
+
+gboolean mm_modem_base_remove_port (MMModemBase *self,
+ MMPort *port);
+
+#endif /* MM_MODEM_BASE_H */
+
diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c
index 5d921c99..01272590 100644
--- a/src/mm-modem-cdma.c
+++ b/src/mm-modem-cdma.c
@@ -7,6 +7,8 @@
#include "mm-callback-info.h"
static void impl_modem_cdma_get_signal_quality (MMModemCdma *modem, DBusGMethodInvocation *context);
+static void impl_modem_cdma_get_esn (MMModemCdma *modem, DBusGMethodInvocation *context);
+static void impl_modem_cdma_get_serving_system (MMModemCdma *modem, DBusGMethodInvocation *context);
#include "mm-modem-cdma-glue.h"
@@ -18,6 +20,33 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
+/*****************************************************************************/
+
+static void
+str_call_done (MMModem *modem, const char *result, 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, result);
+}
+
+static void
+str_call_not_supported (MMModemCdma *self,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_string_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
uint_op_not_supported (MMModem *self,
MMModemUIntFn callback,
@@ -42,6 +71,112 @@ uint_call_done (MMModem *modem, guint32 result, GError *error, gpointer user_dat
dbus_g_method_return (context, result);
}
+static void
+serving_system_call_done (MMModemCdma *self,
+ guint32 class,
+ char band,
+ guint32 sid,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
+
+ if (error)
+ dbus_g_method_return_error (context, error);
+ else {
+ GValueArray *array;
+ GValue value = { 0, };
+ char band_str[2] = { 0, 0 };
+
+ array = g_value_array_new (3);
+
+ /* Band Class */
+ g_value_init (&value, G_TYPE_UINT);
+ g_value_set_uint (&value, class);
+ g_value_array_append (array, &value);
+ g_value_unset (&value);
+
+ /* Band */
+ g_value_init (&value, G_TYPE_STRING);
+ band_str[0] = band;
+ g_value_set_string (&value, band_str);
+ g_value_array_append (array, &value);
+ g_value_unset (&value);
+
+ /* SID */
+ g_value_init (&value, G_TYPE_UINT);
+ g_value_set_uint (&value, sid);
+ g_value_array_append (array, &value);
+ g_value_unset (&value);
+
+ dbus_g_method_return (context, array);
+ }
+}
+
+static void
+serving_system_invoke (MMCallbackInfo *info)
+{
+ MMModemCdmaServingSystemFn callback = (MMModemCdmaServingSystemFn) info->callback;
+
+ callback (MM_MODEM_CDMA (info->modem), 0, 0, 0, info->error, info->user_data);
+}
+
+static void
+serving_system_call_not_supported (MMModemCdma *self,
+ MMModemCdmaServingSystemFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (MM_MODEM (self), serving_system_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);
+}
+
+void
+mm_modem_cdma_get_serving_system (MMModemCdma *self,
+ MMModemCdmaServingSystemFn callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM_CDMA (self));
+ g_return_if_fail (callback != NULL);
+
+ if (MM_MODEM_CDMA_GET_INTERFACE (self)->get_serving_system)
+ MM_MODEM_CDMA_GET_INTERFACE (self)->get_serving_system (self, callback, user_data);
+ else
+ serving_system_call_not_supported (self, callback, user_data);
+}
+
+static void
+impl_modem_cdma_get_serving_system (MMModemCdma *modem,
+ DBusGMethodInvocation *context)
+{
+ mm_modem_cdma_get_serving_system (modem, serving_system_call_done, context);
+}
+
+void
+mm_modem_cdma_get_esn (MMModemCdma *self,
+ MMModemStringFn callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM_CDMA (self));
+ g_return_if_fail (callback != NULL);
+
+ if (MM_MODEM_CDMA_GET_INTERFACE (self)->get_esn)
+ MM_MODEM_CDMA_GET_INTERFACE (self)->get_esn (self, callback, user_data);
+ else
+ str_call_not_supported (self, callback, user_data);
+}
+
+static void
+impl_modem_cdma_get_esn (MMModemCdma *modem,
+ DBusGMethodInvocation *context)
+{
+ mm_modem_cdma_get_esn (modem, str_call_done, context);
+}
+
void
mm_modem_cdma_get_signal_quality (MMModemCdma *self,
MMModemUIntFn callback,
@@ -71,7 +206,6 @@ mm_modem_cdma_signal_quality (MMModemCdma *self,
g_signal_emit (self, signals[SIGNAL_QUALITY], 0, quality);
}
-
/*****************************************************************************/
static void
diff --git a/src/mm-modem-cdma.h b/src/mm-modem-cdma.h
index 7910b63c..6a27a190 100644
--- a/src/mm-modem-cdma.h
+++ b/src/mm-modem-cdma.h
@@ -12,6 +12,13 @@
typedef struct _MMModemCdma MMModemCdma;
+typedef void (*MMModemCdmaServingSystemFn) (MMModemCdma *modem,
+ guint32 class,
+ char band,
+ guint32 sid,
+ GError *error,
+ gpointer user_data);
+
struct _MMModemCdma {
GTypeInterface g_iface;
@@ -20,6 +27,14 @@ struct _MMModemCdma {
MMModemUIntFn callback,
gpointer user_data);
+ void (*get_esn) (MMModemCdma *self,
+ MMModemStringFn callback,
+ gpointer user_data);
+
+ void (*get_serving_system) (MMModemCdma *self,
+ MMModemCdmaServingSystemFn callback,
+ gpointer user_data);
+
/* Signals */
void (*signal_quality) (MMModemCdma *self,
guint32 quality);
@@ -31,6 +46,14 @@ void mm_modem_cdma_get_signal_quality (MMModemCdma *self,
MMModemUIntFn callback,
gpointer user_data);
+void mm_modem_cdma_get_esn (MMModemCdma *self,
+ MMModemStringFn callback,
+ gpointer user_data);
+
+void mm_modem_cdma_get_serving_system (MMModemCdma *self,
+ MMModemCdmaServingSystemFn callback,
+ gpointer user_data);
+
/* Protected */
void mm_modem_cdma_signal_quality (MMModemCdma *self,
diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c
index 85385b25..1ad48cd5 100644
--- a/src/mm-modem-gsm-card.c
+++ b/src/mm-modem-gsm-card.c
@@ -12,9 +12,6 @@ static void impl_gsm_modem_get_imei (MMModemGsmCard *modem,
static void impl_gsm_modem_get_imsi (MMModemGsmCard *modem,
DBusGMethodInvocation *context);
-static void impl_gsm_modem_get_info (MMModemGsmCard *modem,
- DBusGMethodInvocation *context);
-
static void impl_gsm_modem_send_pin (MMModemGsmCard *modem,
const char *pin,
DBusGMethodInvocation *context);
@@ -64,68 +61,6 @@ str_call_not_supported (MMModemGsmCard *self,
}
static void
-info_call_done (MMModemGsmCard *self,
- const char *manufacturer,
- const char *model,
- const char *version,
- GError *error,
- gpointer user_data)
-{
- DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
-
- if (error)
- dbus_g_method_return_error (context, error);
- else {
- GValueArray *array;
- GValue value = { 0, };
-
- array = g_value_array_new (3);
-
- /* Manufacturer */
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_string (&value, manufacturer);
- g_value_array_append (array, &value);
- g_value_unset (&value);
-
- /* Model */
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_string (&value, model);
- g_value_array_append (array, &value);
- g_value_unset (&value);
-
- /* Version */
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_string (&value, version);
- g_value_array_append (array, &value);
- g_value_unset (&value);
-
- dbus_g_method_return (context, array);
- }
-}
-
-static void
-info_invoke (MMCallbackInfo *info)
-{
- MMModemGsmCardInfoFn callback = (MMModemGsmCardInfoFn) info->callback;
-
- callback (MM_MODEM_GSM_CARD (info->modem), NULL, NULL, NULL, info->error, info->user_data);
-}
-
-static void
-info_call_not_supported (MMModemGsmCard *self,
- MMModemGsmCardInfoFn callback,
- gpointer user_data)
-{
- MMCallbackInfo *info;
-
- info = mm_callback_info_new_full (MM_MODEM (self), info_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;
@@ -180,20 +115,6 @@ mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
}
void
-mm_modem_gsm_card_get_info (MMModemGsmCard *self,
- MMModemGsmCardInfoFn callback,
- gpointer user_data)
-{
- g_return_if_fail (MM_IS_MODEM_GSM_CARD (self));
- g_return_if_fail (callback != NULL);
-
- if (MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_info)
- MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_info (self, callback, user_data);
- else
- info_call_not_supported (self, callback, user_data);
-}
-
-void
mm_modem_gsm_card_send_puk (MMModemGsmCard *self,
const char *puk,
const char *pin,
@@ -279,13 +200,6 @@ impl_gsm_modem_get_imsi (MMModemGsmCard *modem,
}
static void
-impl_gsm_modem_get_info (MMModemGsmCard *modem,
- DBusGMethodInvocation *context)
-{
- mm_modem_gsm_card_get_info (modem, info_call_done, context);
-}
-
-static void
impl_gsm_modem_send_puk (MMModemGsmCard *modem,
const char *puk,
const char *pin,
diff --git a/src/mm-modem-gsm-card.h b/src/mm-modem-gsm-card.h
index 50323810..5c6f55f4 100644
--- a/src/mm-modem-gsm-card.h
+++ b/src/mm-modem-gsm-card.h
@@ -12,13 +12,6 @@
typedef struct _MMModemGsmCard MMModemGsmCard;
-typedef void (*MMModemGsmCardInfoFn) (MMModemGsmCard *self,
- const char *manufacturer,
- const char *model,
- const char *version,
- GError *error,
- gpointer user_data);
-
struct _MMModemGsmCard {
GTypeInterface g_iface;
@@ -31,10 +24,6 @@ struct _MMModemGsmCard {
MMModemStringFn callback,
gpointer user_data);
- void (*get_info) (MMModemGsmCard *self,
- MMModemGsmCardInfoFn callback,
- gpointer user_data);
-
void (*send_puk) (MMModemGsmCard *self,
const char *puk,
const char *pin,
@@ -69,10 +58,6 @@ void mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
MMModemStringFn callback,
gpointer user_data);
-void mm_modem_gsm_card_get_info (MMModemGsmCard *self,
- MMModemGsmCardInfoFn callback,
- gpointer user_data);
-
void mm_modem_gsm_card_send_puk (MMModemGsmCard *self,
const char *puk,
const char *pin,
diff --git a/src/mm-modem.c b/src/mm-modem.c
index 7bf913ec..3a566d08 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -10,6 +10,7 @@ static void impl_modem_enable (MMModem *modem, gboolean enable, DBusGMethodInvoc
static void impl_modem_connect (MMModem *modem, const char *number, DBusGMethodInvocation *context);
static void impl_modem_disconnect (MMModem *modem, DBusGMethodInvocation *context);
static void impl_modem_get_ip4_config (MMModem *modem, DBusGMethodInvocation *context);
+static void impl_modem_get_info (MMModem *modem, DBusGMethodInvocation *context);
#include "mm-modem-glue.h"
@@ -196,6 +197,158 @@ impl_modem_disconnect (MMModem *modem,
mm_modem_disconnect (modem, async_call_done, context);
}
+static void
+info_call_done (MMModem *self,
+ const char *manufacturer,
+ const char *model,
+ const char *version,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
+
+ if (error)
+ dbus_g_method_return_error (context, error);
+ else {
+ GValueArray *array;
+ GValue value = { 0, };
+
+ array = g_value_array_new (3);
+
+ /* Manufacturer */
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, manufacturer);
+ g_value_array_append (array, &value);
+ g_value_unset (&value);
+
+ /* Model */
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, model);
+ g_value_array_append (array, &value);
+ g_value_unset (&value);
+
+ /* Version */
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, version);
+ g_value_array_append (array, &value);
+ g_value_unset (&value);
+
+ dbus_g_method_return (context, array);
+ }
+}
+
+static void
+info_invoke (MMCallbackInfo *info)
+{
+ MMModemInfoFn callback = (MMModemInfoFn) info->callback;
+
+ callback (info->modem, NULL, NULL, NULL, info->error, info->user_data);
+}
+
+static void
+info_call_not_supported (MMModem *self,
+ MMModemInfoFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (MM_MODEM (self), info_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);
+}
+
+void
+mm_modem_get_info (MMModem *self,
+ MMModemInfoFn callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM (self));
+ g_return_if_fail (callback != NULL);
+
+ if (MM_MODEM_GET_INTERFACE (self)->get_info)
+ MM_MODEM_GET_INTERFACE (self)->get_info (self, callback, user_data);
+ else
+ info_call_not_supported (self, callback, user_data);
+}
+
+static void
+impl_modem_get_info (MMModem *modem,
+ DBusGMethodInvocation *context)
+{
+ mm_modem_get_info (modem, info_call_done, context);
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_modem_owns_port (MMModem *self,
+ const char *subsys,
+ const char *name)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (MM_IS_MODEM (self), FALSE);
+ g_return_val_if_fail (subsys, FALSE);
+ g_return_val_if_fail (name, FALSE);
+
+ g_assert (MM_MODEM_GET_INTERFACE (self)->owns_port);
+ return MM_MODEM_GET_INTERFACE (self)->owns_port (self, subsys, name);
+}
+
+gboolean
+mm_modem_grab_port (MMModem *self,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (MM_IS_MODEM (self), FALSE);
+ g_return_val_if_fail (subsys, FALSE);
+ g_return_val_if_fail (name, FALSE);
+
+ g_assert (MM_MODEM_GET_INTERFACE (self)->grab_port);
+ return MM_MODEM_GET_INTERFACE (self)->grab_port (self, subsys, name, user_data, error);
+}
+
+void
+mm_modem_release_port (MMModem *self,
+ const char *subsys,
+ const char *name)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (MM_IS_MODEM (self));
+ g_return_if_fail (subsys);
+ g_return_if_fail (name);
+
+ g_assert (MM_MODEM_GET_INTERFACE (self)->release_port);
+ MM_MODEM_GET_INTERFACE (self)->release_port (self, subsys, name);
+}
+
+gboolean
+mm_modem_get_valid (MMModem *self)
+{
+ gboolean valid = FALSE;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (MM_IS_MODEM (self), FALSE);
+
+ g_object_get (G_OBJECT (self), MM_MODEM_VALID, &valid, NULL);
+ return valid;
+}
+
+char *
+mm_modem_get_device (MMModem *self)
+{
+ char *device;
+
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (MM_IS_MODEM (self), NULL);
+
+ g_object_get (G_OBJECT (self), MM_MODEM_MASTER_DEVICE, &device, NULL);
+ return device;
+}
/*****************************************************************************/
@@ -210,9 +363,17 @@ mm_modem_init (gpointer g_iface)
/* Properties */
g_object_interface_install_property
(g_iface,
- g_param_spec_string (MM_MODEM_DEVICE,
- "Device",
+ g_param_spec_string (MM_MODEM_DATA_DEVICE,
"Device",
+ "Data device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_interface_install_property
+ (g_iface,
+ g_param_spec_string (MM_MODEM_MASTER_DEVICE,
+ "MasterDevice",
+ "Master modem parent device of all the modem's ports",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -226,6 +387,14 @@ mm_modem_init (gpointer g_iface)
g_object_interface_install_property
(g_iface,
+ g_param_spec_string (MM_MODEM_PLUGIN,
+ "Plugin",
+ "Plugin name",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_interface_install_property
+ (g_iface,
g_param_spec_uint (MM_MODEM_TYPE,
"Type",
"Type",
@@ -242,6 +411,14 @@ mm_modem_init (gpointer g_iface)
MM_MODEM_IP_METHOD_PPP,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_interface_install_property
+ (g_iface,
+ g_param_spec_boolean (MM_MODEM_VALID,
+ "Valid",
+ "Modem is valid",
+ FALSE,
+ G_PARAM_READABLE));
+
initialized = TRUE;
}
diff --git a/src/mm-modem.h b/src/mm-modem.h
index 914b86a3..9222b703 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -10,13 +10,17 @@
#define MM_IS_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM))
#define MM_MODEM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM, MMModem))
-#define MM_MODEM_DEVICE "device"
-#define MM_MODEM_DRIVER "driver"
-#define MM_MODEM_TYPE "type"
-#define MM_MODEM_IP_METHOD "ip-method"
-
-#define MM_MODEM_TYPE_GSM 1
-#define MM_MODEM_TYPE_CDMA 2
+#define MM_MODEM_DATA_DEVICE "device"
+#define MM_MODEM_MASTER_DEVICE "master-device"
+#define MM_MODEM_DRIVER "driver"
+#define MM_MODEM_TYPE "type"
+#define MM_MODEM_IP_METHOD "ip-method"
+#define MM_MODEM_VALID "valid" /* not exported */
+#define MM_MODEM_PLUGIN "plugin" /* not exported */
+
+#define MM_MODEM_TYPE_UNKNOWN 0
+#define MM_MODEM_TYPE_GSM 1
+#define MM_MODEM_TYPE_CDMA 2
#define MM_MODEM_IP_METHOD_PPP 0
#define MM_MODEM_IP_METHOD_STATIC 1
@@ -25,10 +29,13 @@
typedef enum {
MM_MODEM_PROP_FIRST = 0x1000,
- MM_MODEM_PROP_DEVICE = MM_MODEM_PROP_FIRST,
+ MM_MODEM_PROP_DATA_DEVICE = MM_MODEM_PROP_FIRST,
+ MM_MODEM_PROP_MASTER_DEVICE,
MM_MODEM_PROP_DRIVER,
MM_MODEM_PROP_TYPE,
MM_MODEM_PROP_IP_METHOD,
+ MM_MODEM_PROP_VALID, /* Not exported */
+ MM_MODEM_PROP_PLUGIN, /* Not exported */
} MMModemProp;
typedef struct _MMModem MMModem;
@@ -53,10 +60,31 @@ typedef void (*MMModemIp4Fn) (MMModem *modem,
GError *error,
gpointer user_data);
+typedef void (*MMModemInfoFn) (MMModem *modem,
+ const char *manufacturer,
+ const char *model,
+ const char *version,
+ GError *error,
+ gpointer user_data);
+
struct _MMModem {
GTypeInterface g_iface;
/* Methods */
+ gboolean (*owns_port) (MMModem *self,
+ const char *subsys,
+ const char *name);
+
+ gboolean (*grab_port) (MMModem *self,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error);
+
+ void (*release_port) (MMModem *self,
+ const char *subsys,
+ const char *name);
+
void (*enable) (MMModem *self,
gboolean enable,
MMModemFn callback,
@@ -74,10 +102,28 @@ struct _MMModem {
void (*disconnect) (MMModem *self,
MMModemFn callback,
gpointer user_data);
+
+ void (*get_info) (MMModem *self,
+ MMModemInfoFn callback,
+ gpointer user_data);
};
GType mm_modem_get_type (void);
+gboolean mm_modem_owns_port (MMModem *self,
+ const char *subsys,
+ const char *name);
+
+gboolean mm_modem_grab_port (MMModem *self,
+ const char *subsys,
+ const char *name,
+ gpointer user_data,
+ GError **error);
+
+void mm_modem_release_port (MMModem *self,
+ const char *subsys,
+ const char *name);
+
void mm_modem_enable (MMModem *self,
gboolean enable,
MMModemFn callback,
@@ -96,4 +142,13 @@ void mm_modem_disconnect (MMModem *self,
MMModemFn callback,
gpointer user_data);
+void mm_modem_get_info (MMModem *self,
+ MMModemInfoFn callback,
+ gpointer user_data);
+
+gboolean mm_modem_get_valid (MMModem *self);
+
+char *mm_modem_get_device (MMModem *self);
+
#endif /* MM_MODEM_H */
+
diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c
new file mode 100644
index 00000000..198108cf
--- /dev/null
+++ b/src/mm-plugin-base.c
@@ -0,0 +1,950 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
+#include "mm-plugin-base.h"
+#include "mm-serial-port.h"
+#include "mm-serial-parsers.h"
+#include "mm-errors.h"
+#include "mm-marshal.h"
+
+static void plugin_init (MMPlugin *plugin_class);
+
+G_DEFINE_TYPE_EXTENDED (MMPluginBase, mm_plugin_base, G_TYPE_OBJECT,
+ 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
+
+#define MM_PLUGIN_BASE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_BASE, MMPluginBasePrivate))
+
+/* A hash table shared between all instances of the plugin base that
+ * caches the probed capabilities so that only one plugin has to actually
+ * probe a port.
+ */
+static GHashTable *cached_caps = NULL;
+
+
+typedef struct {
+ char *name;
+ GUdevClient *client;
+
+ GHashTable *modems;
+ GHashTable *tasks;
+} MMPluginBasePrivate;
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ LAST_PROP
+};
+
+enum {
+ PROBE_RESULT,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+typedef enum {
+ PROBE_STATE_GCAP_TRY1 = 0,
+ PROBE_STATE_GCAP_TRY2,
+ PROBE_STATE_GCAP_TRY3,
+ PROBE_STATE_ATI,
+ PROBE_STATE_CGMM,
+ PROBE_STATE_LAST
+} ProbeState;
+
+/*****************************************************************************/
+
+G_DEFINE_TYPE (MMPluginBaseSupportsTask, mm_plugin_base_supports_task, G_TYPE_OBJECT)
+
+#define MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, MMPluginBaseSupportsTaskPrivate))
+
+typedef struct {
+ MMPluginBase *plugin;
+ GUdevDevice *port;
+ GUdevDevice *physdev;
+ char *driver;
+
+ MMSerialPort *probe_port;
+ guint32 probed_caps;
+ ProbeState probe_state;
+ guint probe_id;
+ char *probe_resp;
+ GError *probe_error;
+
+ MMSupportsPortResultFunc callback;
+ gpointer callback_data;
+} MMPluginBaseSupportsTaskPrivate;
+
+static MMPluginBaseSupportsTask *
+supports_task_new (MMPluginBase *self,
+ GUdevDevice *port,
+ GUdevDevice *physdev,
+ const char *driver,
+ MMSupportsPortResultFunc callback,
+ gpointer callback_data)
+{
+ MMPluginBaseSupportsTask *task;
+ MMPluginBaseSupportsTaskPrivate *priv;
+
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE (self), NULL);
+ g_return_val_if_fail (port != NULL, NULL);
+ g_return_val_if_fail (physdev != NULL, NULL);
+ g_return_val_if_fail (driver != NULL, NULL);
+ g_return_val_if_fail (callback != NULL, NULL);
+
+ task = (MMPluginBaseSupportsTask *) g_object_new (MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, NULL);
+
+ priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+ priv->plugin = self;
+ priv->port = g_object_ref (port);
+ priv->physdev = g_object_ref (physdev);
+ priv->driver = g_strdup (driver);
+ priv->callback = callback;
+ priv->callback_data = callback_data;
+
+ return task;
+}
+
+MMPlugin *
+mm_plugin_base_supports_task_get_plugin (MMPluginBaseSupportsTask *task)
+{
+ g_return_val_if_fail (task != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task), NULL);
+
+ return MM_PLUGIN (MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->plugin);
+}
+
+GUdevDevice *
+mm_plugin_base_supports_task_get_port (MMPluginBaseSupportsTask *task)
+{
+ g_return_val_if_fail (task != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task), NULL);
+
+ return MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->port;
+}
+
+GUdevDevice *
+mm_plugin_base_supports_task_get_physdev (MMPluginBaseSupportsTask *task)
+{
+ g_return_val_if_fail (task != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task), NULL);
+
+ return MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->physdev;
+}
+
+const char *
+mm_plugin_base_supports_task_get_driver (MMPluginBaseSupportsTask *task)
+{
+ g_return_val_if_fail (task != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task), NULL);
+
+ return MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->driver;
+}
+
+guint32
+mm_plugin_base_supports_task_get_probed_capabilities (MMPluginBaseSupportsTask *task)
+{
+ g_return_val_if_fail (task != NULL, 0);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task), 0);
+
+ return MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->probed_caps;
+}
+
+void
+mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
+ guint32 level)
+{
+ MMPluginBaseSupportsTaskPrivate *priv;
+ const char *subsys, *name;
+
+ g_return_if_fail (task != NULL);
+ g_return_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task));
+
+ priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+ g_return_if_fail (priv->callback != NULL);
+
+ subsys = g_udev_device_get_subsystem (priv->port);
+ name = g_udev_device_get_name (priv->port);
+
+ priv->callback (MM_PLUGIN (priv->plugin), subsys, name, level, priv->callback_data);
+
+ /* Clear out the callback, it shouldn't be called more than once */
+ priv->callback = NULL;
+ priv->callback_data = NULL;
+}
+
+static void
+mm_plugin_base_supports_task_init (MMPluginBaseSupportsTask *self)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+ MMPluginBaseSupportsTaskPrivate *priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (object);
+
+ g_object_unref (priv->port);
+ g_object_unref (priv->physdev);
+ g_free (priv->driver);
+ g_free (priv->probe_resp);
+ g_clear_error (&(priv->probe_error));
+
+ if (priv->probe_id)
+ g_source_remove (priv->probe_id);
+ if (priv->probe_port)
+ g_object_unref (priv->probe_port);
+
+ G_OBJECT_CLASS (mm_plugin_base_supports_task_parent_class)->dispose (object);
+}
+
+static void
+mm_plugin_base_supports_task_class_init (MMPluginBaseSupportsTaskClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMPluginBaseSupportsTaskPrivate));
+
+ /* Virtual methods */
+ object_class->dispose = dispose;
+}
+
+/*****************************************************************************/
+
+#define MM_PLUGIN_BASE_PORT_CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
+ MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856 | \
+ MM_PLUGIN_BASE_PORT_CAP_IS856_A)
+
+#define CAP_GSM_OR_CDMA (MM_PLUGIN_BASE_PORT_CAP_CDMA | MM_PLUGIN_BASE_PORT_CAP_GSM)
+
+struct modem_caps {
+ char *name;
+ guint32 bits;
+};
+
+static struct modem_caps modem_caps[] = {
+ {"+CGSM", MM_PLUGIN_BASE_PORT_CAP_GSM},
+ {"+CIS707-A", MM_PLUGIN_BASE_PORT_CAP_IS707_A},
+ {"+CIS707A", MM_PLUGIN_BASE_PORT_CAP_IS707_A}, /* Cmotech */
+ {"+CIS707", MM_PLUGIN_BASE_PORT_CAP_IS707_A},
+ {"CIS707", MM_PLUGIN_BASE_PORT_CAP_IS707_A}, /* Qualcomm Gobi */
+ {"+CIS707P", MM_PLUGIN_BASE_PORT_CAP_IS707_P},
+ {"CIS-856", MM_PLUGIN_BASE_PORT_CAP_IS856},
+ {"+IS-856", MM_PLUGIN_BASE_PORT_CAP_IS856}, /* Cmotech */
+ {"CIS-856-A", MM_PLUGIN_BASE_PORT_CAP_IS856_A},
+ {"CIS-856A", MM_PLUGIN_BASE_PORT_CAP_IS856_A}, /* Kyocera KPC680 */
+ {"+DS", MM_PLUGIN_BASE_PORT_CAP_DS},
+ {"+ES", MM_PLUGIN_BASE_PORT_CAP_ES},
+ {"+MS", MM_PLUGIN_BASE_PORT_CAP_MS},
+ {"+FCLASS", MM_PLUGIN_BASE_PORT_CAP_FCLASS},
+ {NULL}
+};
+
+static guint32
+parse_gcap (const char *buf)
+{
+ struct modem_caps *cap = modem_caps;
+ guint32 ret = 0;
+
+ while (cap->name) {
+ if (strstr (buf, cap->name))
+ ret |= cap->bits;
+ cap++;
+ }
+ return ret;
+}
+
+static guint32
+parse_cgmm (const char *buf)
+{
+ if (strstr (buf, "GSM900") || strstr (buf, "GSM1800") ||
+ strstr (buf, "GSM1900") || strstr (buf, "GSM850"))
+ return MM_PLUGIN_BASE_PORT_CAP_GSM;
+ return 0;
+}
+
+static gboolean
+emit_probe_result (gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data);
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+ MMPlugin *self = mm_plugin_base_supports_task_get_plugin (task);
+
+ /* Close the serial port */
+ g_object_unref (task_priv->probe_port);
+ task_priv->probe_port = NULL;
+
+ task_priv->probe_id = 0;
+ g_signal_emit (self, signals[PROBE_RESULT], 0, task, task_priv->probed_caps);
+ return FALSE;
+}
+
+static void
+probe_complete (MMPluginBaseSupportsTask *task)
+{
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+
+ g_hash_table_insert (cached_caps,
+ g_strdup (mm_port_get_device (MM_PORT (task_priv->probe_port))),
+ GUINT_TO_POINTER (task_priv->probed_caps));
+
+ task_priv->probe_id = g_idle_add (emit_probe_result, task);
+}
+
+static void
+parse_response (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data);
+
+static void
+real_handle_probe_response (MMPluginBase *self,
+ MMPluginBaseSupportsTask *task,
+ const char *cmd,
+ const char *response,
+ const GError *error)
+{
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+ MMSerialPort *port = task_priv->probe_port;
+ gboolean ignore_error = FALSE;
+
+ task_priv->probe_state++;
+
+ /* Some modems (Huawei E160g) won't respond to +GCAP with no SIM, but
+ * will respond to ATI.
+ */
+ if (response && strstr (response, "+CME ERROR:"))
+ ignore_error = TRUE;
+
+ if (error && !ignore_error) {
+ if (error->code == MM_SERIAL_RESPONSE_TIMEOUT) {
+ /* Try GCAP again */
+ if (task_priv->probe_state <= PROBE_STATE_GCAP_TRY3) {
+ mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, task);
+ return;
+ }
+
+ /* Otherwise, if all the GCAP tries timed out, ignore the port
+ * as it's probably not an AT-capable port.
+ */
+ probe_complete (task);
+ } else if (task_priv->probe_state <= PROBE_STATE_GCAP_TRY3) {
+ mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, task);
+ } else if (task_priv->probe_state == PROBE_STATE_ATI) {
+ /* Give ATI a try */
+ mm_serial_port_queue_command (port, "I", 3, parse_response, task);
+ } else if (task_priv->probe_state == PROBE_STATE_CGMM) {
+ /* If CGMM failed, probably not a modem port */
+ probe_complete (task);
+ }
+ return;
+ }
+
+ if (response) {
+ /* Parse the response */
+ task_priv->probed_caps = parse_gcap (response);
+
+ /* Some models (BUSlink SCWi275u) stick stupid stuff in the GMM response */
+ if ( (task_priv->probe_state == PROBE_STATE_LAST)
+ && !(task_priv->probed_caps & CAP_GSM_OR_CDMA))
+ task_priv->probed_caps = parse_cgmm (response);
+
+ if (task_priv->probed_caps & CAP_GSM_OR_CDMA) {
+ probe_complete (task);
+ return;
+ }
+ }
+
+ /* Try a different command */
+ switch (task_priv->probe_state) {
+ case PROBE_STATE_GCAP_TRY1:
+ case PROBE_STATE_GCAP_TRY2:
+ case PROBE_STATE_GCAP_TRY3:
+ mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, task);
+ break;
+ case PROBE_STATE_ATI:
+ /* After the last GCAP attempt, try ATI */
+ mm_serial_port_queue_command (port, "I", 3, parse_response, task);
+ break;
+ case PROBE_STATE_CGMM:
+ /* After the ATI attempt, try CGMM */
+ mm_serial_port_queue_command (port, "+CGMM", 3, parse_response, task);
+ break;
+ default:
+ /* Probably not GSM or CDMA */
+ probe_complete (task);
+ break;
+ }
+}
+
+static gboolean
+handle_probe_response (gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data);
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+ MMPluginBase *self = MM_PLUGIN_BASE (mm_plugin_base_supports_task_get_plugin (task));
+ const char *cmd = NULL;
+
+ switch (task_priv->probe_state) {
+ case PROBE_STATE_GCAP_TRY1:
+ case PROBE_STATE_GCAP_TRY2:
+ case PROBE_STATE_GCAP_TRY3:
+ cmd = "+GCAP";
+ break;
+ case PROBE_STATE_ATI:
+ cmd = "I";
+ break;
+ case PROBE_STATE_CGMM:
+ default:
+ cmd = "+CGMM";
+ break;
+ }
+
+ MM_PLUGIN_BASE_GET_CLASS (self)->handle_probe_response (self,
+ task,
+ cmd,
+ task_priv->probe_resp,
+ task_priv->probe_error);
+ return FALSE;
+}
+
+static void
+parse_response (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data);
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+
+ if (task_priv->probe_id)
+ g_source_remove (task_priv->probe_id);
+ g_free (task_priv->probe_resp);
+ task_priv->probe_resp = NULL;
+ g_clear_error (&(task_priv->probe_error));
+
+ if (response && response->len)
+ task_priv->probe_resp = g_strdup (response->str);
+ if (error)
+ task_priv->probe_error = g_error_copy (error);
+
+ /* Schedule the response handler in an idle, since we can't emit the
+ * PROBE_RESULT signal from the serial port response handler without
+ * potentially destroying the serial port in the middle of its response
+ * handler, which it understandably doesn't like.
+ */
+ task_priv->probe_id = g_idle_add (handle_probe_response, task);
+}
+
+static void
+flash_done (MMSerialPort *port, gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data);
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+
+ task_priv->probe_id = 0;
+ mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, user_data);
+}
+
+gboolean
+mm_plugin_base_probe_port (MMPluginBase *self,
+ MMPluginBaseSupportsTask *task,
+ GError **error)
+{
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+ MMSerialPort *serial;
+ const char *name;
+ GUdevDevice *port;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE (self), FALSE);
+ g_return_val_if_fail (task != NULL, FALSE);
+
+ port = mm_plugin_base_supports_task_get_port (task);
+ g_assert (port);
+ name = g_udev_device_get_name (port);
+ g_assert (name);
+
+ serial = mm_serial_port_new (name, MM_PORT_TYPE_PRIMARY);
+ g_object_set (serial,
+ MM_SERIAL_PORT_SEND_DELAY, 100000,
+ MM_PORT_CARRIER_DETECT, FALSE,
+ NULL);
+
+ mm_serial_port_set_response_parser (serial,
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
+
+ if (!mm_serial_port_open (serial, error)) {
+ g_object_unref (serial);
+ return FALSE;
+ }
+
+ g_debug ("(%s): probe requested by plugin '%s'", name, priv->name);
+ task_priv->probe_port = serial;
+ task_priv->probe_id = mm_serial_port_flash (serial, 100, flash_done, task);
+ return TRUE;
+}
+
+gboolean
+mm_plugin_base_get_cached_port_capabilities (MMPluginBase *self,
+ GUdevDevice *port,
+ guint32 *capabilities)
+{
+ gpointer tmp = NULL;
+ gboolean found;
+
+ found = g_hash_table_lookup_extended (cached_caps, g_udev_device_get_name (port), NULL, tmp);
+ *capabilities = GPOINTER_TO_UINT (tmp);
+ return found;
+}
+
+/*****************************************************************************/
+
+static void
+modem_destroyed (gpointer data, GObject *modem)
+{
+ MMPluginBase *self = MM_PLUGIN_BASE (data);
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ GHashTableIter iter;
+ gpointer key, value;
+
+ /* Remove it from the modems info */
+ g_hash_table_iter_init (&iter, priv->modems);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ if (value == modem) {
+ g_hash_table_iter_remove (&iter);
+ break;
+ }
+ }
+
+ /* Since we don't track port cached capabilities on a per-modem basis,
+ * we just have to live with blowing away the cached capabilities whenever
+ * a modem gets removed. Could do better here by storing a structure
+ * in the cached capabilities table that includes { caps, modem device }
+ * or something and then only removing cached capabilities for ports
+ * that the modem that was just removed owned, but whatever.
+ */
+ g_hash_table_remove_all (cached_caps);
+}
+
+MMModem *
+mm_plugin_base_find_modem (MMPluginBase *self,
+ const char *master_device)
+{
+ MMPluginBasePrivate *priv;
+
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE (self), NULL);
+ g_return_val_if_fail (master_device != NULL, NULL);
+ g_return_val_if_fail (strlen (master_device) > 0, NULL);
+
+ priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ return g_hash_table_lookup (priv->modems, master_device);
+}
+
+/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
+
+static int hex2num (char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+static int hex2byte (const char *hex)
+{
+ int a, b;
+ a = hex2num(*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+/* End from hostap */
+
+gboolean
+mm_plugin_base_get_device_ids (MMPluginBase *self,
+ const char *subsys,
+ const char *name,
+ guint16 *vendor,
+ guint16 *product)
+{
+ MMPluginBasePrivate *priv;
+ GUdevDevice *device = NULL;
+ const char *vid, *pid;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (MM_IS_PLUGIN_BASE (self), FALSE);
+ g_return_val_if_fail (subsys != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ if (vendor)
+ g_return_val_if_fail (*vendor == 0, FALSE);
+ if (product)
+ g_return_val_if_fail (*product == 0, FALSE);
+
+ priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+
+ device = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name);
+ if (!device)
+ goto out;
+
+ vid = g_udev_device_get_property (device, "ID_VENDOR_ID");
+ if (!vid || (strlen (vid) != 4))
+ goto out;
+
+ if (vendor) {
+ *vendor = (guint16) (hex2byte (vid + 2) & 0xFF);
+ *vendor |= (guint16) ((hex2byte (vid) & 0xFF) << 8);
+ }
+
+ pid = g_udev_device_get_property (device, "ID_MODEL_ID");
+ if (!pid || (strlen (pid) != 4)) {
+ *vendor = 0;
+ goto out;
+ }
+
+ if (product) {
+ *product = (guint16) (hex2byte (pid + 2) & 0xFF);
+ *product |= (guint16) ((hex2byte (pid) & 0xFF) << 8);
+ }
+
+ success = TRUE;
+
+out:
+ if (device)
+ g_object_unref (device);
+ return success;
+}
+
+static char *
+get_key (const char *subsys, const char *name)
+{
+ return g_strdup_printf ("%s%s", subsys, name);
+}
+
+static const char *
+get_name (MMPlugin *plugin)
+{
+ return MM_PLUGIN_BASE_GET_PRIVATE (plugin)->name;
+}
+
+static char *
+get_driver_name (GUdevDevice *device)
+{
+ GUdevDevice *parent = NULL;
+ const char *driver;
+ char *ret;
+
+ driver = g_udev_device_get_driver (device);
+ if (!driver) {
+ parent = g_udev_device_get_parent (device);
+ if (parent)
+ driver = g_udev_device_get_driver (parent);
+ }
+
+ if (driver)
+ ret = g_strdup (driver);
+ if (parent)
+ g_object_unref (parent);
+
+ return ret;
+}
+
+static GUdevDevice *
+real_find_physical_device (MMPluginBase *plugin, GUdevDevice *child)
+{
+ GUdevDevice *iter, *old = NULL;
+ GUdevDevice *physdev = NULL;
+ const char *subsys, *type;
+ guint32 i = 0;
+ gboolean is_usb = FALSE, is_pci = FALSE;
+
+ g_return_val_if_fail (child != NULL, NULL);
+
+ iter = g_object_ref (child);
+ while (iter && i++ < 5) {
+ subsys = g_udev_device_get_subsystem (iter);
+ if (subsys) {
+ if (is_usb || !strcmp (subsys, "usb")) {
+ is_usb = TRUE;
+ type = g_udev_device_get_devtype (iter);
+ if (type && !strcmp (type, "usb_device")) {
+ physdev = iter;
+ break;
+ }
+ } else if (is_pci || !strcmp (subsys, "pci")) {
+ is_pci = TRUE;
+ physdev = iter;
+ break;
+ }
+ }
+
+ old = iter;
+ iter = g_udev_device_get_parent (old);
+ g_object_unref (old);
+ }
+
+ return physdev;
+}
+
+static MMPluginSupportsResult
+supports_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ MMSupportsPortResultFunc callback,
+ gpointer callback_data)
+{
+ MMPluginBase *self = MM_PLUGIN_BASE (plugin);
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ GUdevDevice *port = NULL, *physdev = NULL;
+ char *driver = NULL, *key = NULL;
+ MMPluginBaseSupportsTask *task;
+ MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ MMModem *existing;
+ const char *master_path;
+
+ key = get_key (subsys, name);
+ task = g_hash_table_lookup (priv->tasks, key);
+ if (task) {
+ g_free (key);
+ g_return_val_if_fail (task == NULL, MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
+ }
+
+ port = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name);
+ if (!port)
+ goto out;
+
+ physdev = MM_PLUGIN_BASE_GET_CLASS (self)->find_physical_device (self, port);
+ if (!physdev)
+ goto out;
+
+ driver = get_driver_name (port);
+ if (!driver)
+ goto out;
+
+ task = supports_task_new (self, port, physdev, driver, callback, callback_data);
+ g_assert (task);
+ g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task));
+
+ /* Help the plugin out a bit by finding an existing modem for this port */
+ master_path = g_udev_device_get_sysfs_path (physdev);
+ existing = g_hash_table_lookup (priv->modems, master_path);
+
+ result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self, existing, task);
+ if (result != MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) {
+ /* If the plugin doesn't support the port at all, the supports task is
+ * not needed.
+ */
+ g_hash_table_remove (priv->tasks, key);
+ }
+ g_object_unref (task);
+
+out:
+ if (physdev)
+ g_object_unref (physdev);
+ if (port)
+ g_object_unref (port);
+ g_free (key);
+ g_free (driver);
+ return result;
+}
+
+static void
+cancel_supports_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name)
+{
+ MMPluginBase *self = MM_PLUGIN_BASE (plugin);
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ MMPluginBaseSupportsTask *task;
+ char *key;
+
+ key = get_key (subsys, name);
+ task = g_hash_table_lookup (priv->tasks, key);
+ if (task) {
+ /* Let the plugin cancel any ongoing tasks */
+ if (MM_PLUGIN_BASE_GET_CLASS (self)->cancel_task)
+ MM_PLUGIN_BASE_GET_CLASS (self)->cancel_task (self, task);
+ g_hash_table_remove (priv->tasks, key);
+ }
+
+ g_free (key);
+}
+
+static MMModem *
+grab_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ GError **error)
+{
+ MMPluginBase *self = MM_PLUGIN_BASE (plugin);
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ MMPluginBaseSupportsTask *task;
+ char *key;
+ MMModem *existing = NULL, *modem = NULL;
+ const char *master_path;
+
+ key = get_key (subsys, name);
+ task = g_hash_table_lookup (priv->tasks, key);
+ if (!task) {
+ g_free (key);
+ g_return_val_if_fail (task != NULL, FALSE);
+ }
+
+ /* Help the plugin out a bit by finding an existing modem for this port */
+ master_path = g_udev_device_get_sysfs_path (mm_plugin_base_supports_task_get_physdev (task));
+ existing = g_hash_table_lookup (priv->modems, master_path);
+
+ /* Let the modem grab the port */
+ modem = MM_PLUGIN_BASE_GET_CLASS (self)->grab_port (self, existing, task, error);
+ if (modem && !existing) {
+ g_hash_table_insert (priv->modems, g_strdup (master_path), modem);
+ g_object_weak_ref (G_OBJECT (modem), modem_destroyed, self);
+ }
+
+ g_hash_table_remove (priv->tasks, key);
+ g_free (key);
+ return modem;
+}
+
+/*****************************************************************************/
+
+static void
+plugin_init (MMPlugin *plugin_class)
+{
+ /* interface implementation */
+ plugin_class->get_name = get_name;
+ plugin_class->supports_port = supports_port;
+ plugin_class->cancel_supports_port = cancel_supports_port;
+ plugin_class->grab_port = grab_port;
+}
+
+static void
+mm_plugin_base_init (MMPluginBase *self)
+{
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
+ const char *subsys[] = { "tty", "net", NULL };
+
+ if (!cached_caps)
+ cached_caps = g_hash_table_new (g_str_hash, g_str_equal);
+
+ priv->client = g_udev_client_new (subsys);
+
+ priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ priv->tasks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) g_object_unref);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ /* Construct only */
+ priv->name = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, priv->name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+finalize (GObject *object)
+{
+ MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (object);
+
+ g_free (priv->name);
+
+ g_object_unref (priv->client);
+
+ g_hash_table_destroy (priv->modems);
+ g_hash_table_destroy (priv->tasks);
+
+ G_OBJECT_CLASS (mm_plugin_base_parent_class)->finalize (object);
+}
+
+static void
+mm_plugin_base_class_init (MMPluginBaseClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMPluginBasePrivate));
+
+ klass->find_physical_device = real_find_physical_device;
+ klass->handle_probe_response = real_handle_probe_response;
+
+ /* Virtual methods */
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->finalize = finalize;
+
+ g_object_class_install_property
+ (object_class, PROP_NAME,
+ g_param_spec_string (MM_PLUGIN_BASE_NAME,
+ "Name",
+ "Name",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ signals[PROBE_RESULT] =
+ g_signal_new ("probe-result",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (MMPluginBaseClass, probe_result),
+ NULL, NULL,
+ mm_marshal_VOID__OBJECT_UINT,
+ G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_UINT);
+}
diff --git a/src/mm-plugin-base.h b/src/mm-plugin-base.h
new file mode 100644
index 00000000..91d3ddba
--- /dev/null
+++ b/src/mm-plugin-base.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_PLUGIN_BASE_H
+#define MM_PLUGIN_BASE_H
+
+#include <glib.h>
+#include <glib/gtypes.h>
+#include <glib-object.h>
+
+#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
+#include <gudev/gudev.h>
+
+#include "mm-plugin.h"
+#include "mm-modem.h"
+#include "mm-port.h"
+
+#define MM_PLUGIN_BASE_PORT_CAP_GSM 0x0001 /* GSM */
+#define MM_PLUGIN_BASE_PORT_CAP_IS707_A 0x0002 /* CDMA Circuit Switched Data */
+#define MM_PLUGIN_BASE_PORT_CAP_IS707_P 0x0004 /* CDMA Packet Switched Data */
+#define MM_PLUGIN_BASE_PORT_CAP_DS 0x0008 /* Data compression selection (v.42bis) */
+#define MM_PLUGIN_BASE_PORT_CAP_ES 0x0010 /* Error control selection (v.42) */
+#define MM_PLUGIN_BASE_PORT_CAP_FCLASS 0x0020 /* Group III Fax */
+#define MM_PLUGIN_BASE_PORT_CAP_MS 0x0040 /* Modulation selection */
+#define MM_PLUGIN_BASE_PORT_CAP_W 0x0080 /* Wireless commands */
+#define MM_PLUGIN_BASE_PORT_CAP_IS856 0x0100 /* CDMA 3G EVDO rev 0 */
+#define MM_PLUGIN_BASE_PORT_CAP_IS856_A 0x0200 /* CDMA 3G EVDO rev A */
+
+#define MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK (mm_plugin_base_supports_task_get_type ())
+#define MM_PLUGIN_BASE_SUPPORTS_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, MMPluginBaseSupportsTask))
+#define MM_PLUGIN_BASE_SUPPORTS_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, MMPluginBaseSupportsTaskClass))
+#define MM_IS_PLUGIN_BASE_SUPPORTS_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK))
+#define MM_IS_PLUBIN_BASE_SUPPORTS_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK))
+#define MM_PLUGIN_BASE_SUPPORTS_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, MMPluginBaseSupportsTaskClass))
+
+typedef struct {
+ GObject parent;
+} MMPluginBaseSupportsTask;
+
+typedef struct {
+ GObjectClass parent;
+} MMPluginBaseSupportsTaskClass;
+
+GType mm_plugin_base_supports_task_get_type (void);
+
+MMPlugin *mm_plugin_base_supports_task_get_plugin (MMPluginBaseSupportsTask *task);
+
+GUdevDevice *mm_plugin_base_supports_task_get_port (MMPluginBaseSupportsTask *task);
+
+GUdevDevice *mm_plugin_base_supports_task_get_physdev (MMPluginBaseSupportsTask *task);
+
+const char *mm_plugin_base_supports_task_get_driver (MMPluginBaseSupportsTask *task);
+
+guint32 mm_plugin_base_supports_task_get_probed_capabilities (MMPluginBaseSupportsTask *task);
+
+void mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
+ guint32 level);
+
+
+#define MM_TYPE_PLUGIN_BASE (mm_plugin_base_get_type ())
+#define MM_PLUGIN_BASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_BASE, MMPluginBase))
+#define MM_PLUGIN_BASE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_BASE, MMPluginBaseClass))
+#define MM_IS_PLUGIN_BASE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_BASE))
+#define MM_IS_PLUBIN_BASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_BASE))
+#define MM_PLUGIN_BASE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_BASE, MMPluginBaseClass))
+
+#define MM_PLUGIN_BASE_NAME "name"
+
+typedef struct _MMPluginBase MMPluginBase;
+typedef struct _MMPluginBaseClass MMPluginBaseClass;
+
+struct _MMPluginBase {
+ GObject parent;
+};
+
+struct _MMPluginBaseClass {
+ GObjectClass parent;
+
+ /* Mandatory subclass functions */
+ MMPluginSupportsResult (*supports_port) (MMPluginBase *plugin,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task);
+
+ MMModem *(*grab_port) (MMPluginBase *plugin,
+ MMModem *existing,
+ MMPluginBaseSupportsTask *task,
+ GError **error);
+
+ /* Optional subclass functions */
+ void (*cancel_task) (MMPluginBase *plugin,
+ MMPluginBaseSupportsTask *task);
+
+ /* Find a the physical device of a port, ie the USB or PCI or whatever
+ * "master" device that owns the port. The GUdevDevice object returned
+ * will be unref-ed by the caller.
+ */
+ GUdevDevice * (*find_physical_device) (MMPluginBase *plugin,
+ GUdevDevice *port);
+
+ void (*handle_probe_response) (MMPluginBase *plugin,
+ MMPluginBaseSupportsTask *task,
+ const char *command,
+ const char *response,
+ const GError *error);
+
+ /* Signals */
+ void (*probe_result) (MMPluginBase *self,
+ MMPluginBaseSupportsTask *task,
+ guint32 capabilities);
+};
+
+GType mm_plugin_base_get_type (void);
+
+MMModem *mm_plugin_base_find_modem (MMPluginBase *self,
+ const char *master_device);
+
+gboolean mm_plugin_base_get_device_ids (MMPluginBase *self,
+ const char *subsys,
+ const char *name,
+ guint16 *vendor,
+ guint16 *product);
+
+gboolean mm_plugin_base_probe_port (MMPluginBase *self,
+ MMPluginBaseSupportsTask *task,
+ GError **error);
+
+/* Returns TRUE if the port was previously probed, FALSE if not */
+gboolean mm_plugin_base_get_cached_port_capabilities (MMPluginBase *self,
+ GUdevDevice *port,
+ guint32 *capabilities);
+
+#endif /* MM_PLUGIN_BASE_H */
+
diff --git a/src/mm-plugin.c b/src/mm-plugin.c
index e1fd21c1..12df9dab 100644
--- a/src/mm-plugin.c
+++ b/src/mm-plugin.c
@@ -10,49 +10,46 @@ mm_plugin_get_name (MMPlugin *plugin)
return MM_PLUGIN_GET_INTERFACE (plugin)->get_name (plugin);
}
-char **
-mm_plugin_list_supported_udis (MMPlugin *plugin,
- LibHalContext *hal_ctx)
+MMPluginSupportsResult
+mm_plugin_supports_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ MMSupportsPortResultFunc callback,
+ gpointer user_data)
{
- g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL);
- g_return_val_if_fail (hal_ctx != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PLUGIN (plugin), FALSE);
+ g_return_val_if_fail (subsys != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (callback != NULL, FALSE);
- return MM_PLUGIN_GET_INTERFACE (plugin)->list_supported_udis (plugin, hal_ctx);
+ return MM_PLUGIN_GET_INTERFACE (plugin)->supports_port (plugin, subsys, name, callback, user_data);
}
-gboolean
-mm_plugin_supports_udi (MMPlugin *plugin,
- LibHalContext *hal_ctx,
- const char *udi)
+void
+mm_plugin_cancel_supports_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name)
{
- g_return_val_if_fail (MM_IS_PLUGIN (plugin), FALSE);
- g_return_val_if_fail (hal_ctx != NULL, FALSE);
- g_return_val_if_fail (udi != NULL, FALSE);
+ g_return_if_fail (MM_IS_PLUGIN (plugin));
+ g_return_if_fail (subsys != NULL);
+ g_return_if_fail (name != NULL);
- return MM_PLUGIN_GET_INTERFACE (plugin)->supports_udi (plugin, hal_ctx, udi);
+ MM_PLUGIN_GET_INTERFACE (plugin)->cancel_supports_port (plugin, subsys, name);
}
MMModem *
-mm_plugin_create_modem (MMPlugin *plugin,
- LibHalContext *hal_ctx,
- const char *udi)
+mm_plugin_grab_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ GError **error)
{
- MMModem *modem;
-
- g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL);
- g_return_val_if_fail (hal_ctx != NULL, NULL);
- g_return_val_if_fail (udi != NULL, NULL);
-
- modem = MM_PLUGIN_GET_INTERFACE (plugin)->create_modem (plugin, hal_ctx, udi);
- if (modem)
- g_debug ("Created new %s modem (%s)", mm_plugin_get_name (plugin), udi);
- else
- g_warning ("Failed to create %s modem (%s)", mm_plugin_get_name (plugin), udi);
+ g_return_val_if_fail (MM_IS_PLUGIN (plugin), FALSE);
+ g_return_val_if_fail (subsys != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
- return modem;
+ return MM_PLUGIN_GET_INTERFACE (plugin)->grab_port (plugin, subsys, name, error);
}
-
/*****************************************************************************/
static void
diff --git a/src/mm-plugin.h b/src/mm-plugin.h
index 0f9a600b..3fa3a2cb 100644
--- a/src/mm-plugin.h
+++ b/src/mm-plugin.h
@@ -4,10 +4,11 @@
#define MM_PLUGIN_H
#include <glib-object.h>
-#include <libhal.h>
#include <mm-modem.h>
-#define MM_PLUGIN_MAJOR_VERSION 1
+#define MM_PLUGIN_GENERIC_NAME "Generic"
+
+#define MM_PLUGIN_MAJOR_VERSION 3
#define MM_PLUGIN_MINOR_VERSION 0
#define MM_TYPE_PLUGIN (mm_plugin_get_type ())
@@ -19,37 +20,87 @@ typedef struct _MMPlugin MMPlugin;
typedef MMPlugin *(*MMPluginCreateFunc) (void);
+/*
+ * 'level' is a value between 0 and 100 inclusive, where 0 means the plugin has
+ * no support for the port, and 100 means the plugin has full support for the
+ * port.
+ */
+typedef void (*MMSupportsPortResultFunc) (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ guint32 level,
+ gpointer user_data);
+
+typedef enum {
+ MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED = 0x0,
+ MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS,
+ MM_PLUGIN_SUPPORTS_PORT_DEFER
+} MMPluginSupportsResult;
+
struct _MMPlugin {
GTypeInterface g_iface;
/* Methods */
- const char *(*get_name) (MMPlugin *self);
-
- char **(*list_supported_udis) (MMPlugin *self,
- LibHalContext *hal_ctx);
-
- gboolean (*supports_udi) (MMPlugin *self,
- LibHalContext *hal_ctx,
- const char *udi);
-
- MMModem *(*create_modem) (MMPlugin *self,
- LibHalContext *hal_ctx,
- const char *udi);
+ const char *(*get_name) (MMPlugin *self);
+
+ /* Check whether a plugin supports a particular modem port, and what level
+ * of support the plugin has for the device. If the plugin can immediately
+ * determine whether a port is unsupported, it should return
+ * FALSE. Otherwise, if the plugin needs to perform additional operations
+ * (ie, probing) to determine the level of support or additional details
+ * about a port, it should queue that operation (but *not* block on the
+ * result) and return TRUE to indicate the operation is ongoing. When the
+ * operation is finished or the level of support is known, the plugin should
+ * call the provided callback and pass that callback the provided user_data.
+ */
+ MMPluginSupportsResult (*supports_port) (MMPlugin *self,
+ const char *subsys,
+ const char *name,
+ MMSupportsPortResultFunc callback,
+ gpointer user_data);
+
+ /* Called to cancel an ongoing supports_port() operation or to notify the
+ * plugin to clean up that operation. For example, if two plugins support
+ * a particular port, but the first plugin grabs the port, this method will
+ * be called on the second plugin to allow that plugin to clean up resources
+ * used while determining it's level of support for the port.
+ */
+ void (*cancel_supports_port) (MMPlugin *self,
+ const char *subsys,
+ const char *name);
+
+ /* Will only be called if the plugin returns a value greater than 0 for
+ * the supports_port() method for this port. The plugin should create and
+ * return a new modem for the port's device if there is no existing modem
+ * to handle the port's hardware device, or should add the port to an
+ * existing modem and return that modem object. If an error is encountered
+ * while claiming the port, the error information should be returned in the
+ * error argument, and the plugin should return NULL.
+ */
+ MMModem * (*grab_port) (MMPlugin *self,
+ const char *subsys,
+ const char *name,
+ GError **error);
};
GType mm_plugin_get_type (void);
-const char *mm_plugin_get_name (MMPlugin *plugin);
+const char *mm_plugin_get_name (MMPlugin *plugin);
-char **mm_plugin_list_supported_udis (MMPlugin *plugin,
- LibHalContext *hal_ctx);
+MMPluginSupportsResult mm_plugin_supports_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ MMSupportsPortResultFunc callback,
+ gpointer user_data);
-gboolean mm_plugin_supports_udi (MMPlugin *plugin,
- LibHalContext *hal_ctx,
- const char *udi);
+void mm_plugin_cancel_supports_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name);
-MMModem *mm_plugin_create_modem (MMPlugin *plugin,
- LibHalContext *hal_ctx,
- const char *udi);
+MMModem *mm_plugin_grab_port (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ GError **error);
#endif /* MM_PLUGIN_H */
+
diff --git a/src/mm-port.c b/src/mm-port.c
new file mode 100644
index 00000000..715db958
--- /dev/null
+++ b/src/mm-port.c
@@ -0,0 +1,238 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "mm-port.h"
+
+G_DEFINE_TYPE (MMPort, mm_port, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ PROP_SUBSYS,
+ PROP_TYPE,
+ PROP_CARRIER_DETECT,
+
+ LAST_PROP
+};
+
+#define MM_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PORT, MMPortPrivate))
+
+typedef struct {
+ char *device;
+ MMPortSubsys subsys;
+ MMPortType ptype;
+ gboolean carrier_detect;
+} MMPortPrivate;
+
+/*****************************************************************************/
+
+static GObject*
+constructor (GType type,
+ guint n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ MMPortPrivate *priv;
+
+ object = G_OBJECT_CLASS (mm_port_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+ if (!object)
+ return NULL;
+
+ priv = MM_PORT_GET_PRIVATE (object);
+
+ if (!priv->device) {
+ g_warning ("MMPort: no device provided");
+ g_object_unref (object);
+ return NULL;
+ }
+
+ if (priv->subsys == MM_PORT_SUBSYS_UNKNOWN) {
+ g_warning ("MMPort: invalid port subsystem");
+ g_object_unref (object);
+ return NULL;
+ }
+
+ if (priv->ptype == MM_PORT_TYPE_UNKNOWN) {
+ g_warning ("MMPort: invalid port type");
+ g_object_unref (object);
+ return NULL;
+ }
+
+ return object;
+}
+
+
+const char *
+mm_port_get_device (MMPort *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (MM_IS_PORT (self), NULL);
+
+ return MM_PORT_GET_PRIVATE (self)->device;
+}
+
+MMPortSubsys
+mm_port_get_subsys (MMPort *self)
+{
+ g_return_val_if_fail (self != NULL, MM_PORT_SUBSYS_UNKNOWN);
+ g_return_val_if_fail (MM_IS_PORT (self), MM_PORT_SUBSYS_UNKNOWN);
+
+ return MM_PORT_GET_PRIVATE (self)->subsys;
+}
+
+MMPortType
+mm_port_get_port_type (MMPort *self)
+{
+ g_return_val_if_fail (self != NULL, MM_PORT_TYPE_UNKNOWN);
+ g_return_val_if_fail (MM_IS_PORT (self), MM_PORT_TYPE_UNKNOWN);
+
+ return MM_PORT_GET_PRIVATE (self)->ptype;
+}
+
+gboolean
+mm_port_get_carrier_detect (MMPort *self)
+{
+ g_return_val_if_fail (self != NULL, MM_PORT_TYPE_UNKNOWN);
+ g_return_val_if_fail (MM_IS_PORT (self), MM_PORT_TYPE_UNKNOWN);
+
+ return MM_PORT_GET_PRIVATE (self)->carrier_detect;
+}
+
+/*****************************************************************************/
+
+static void
+mm_port_init (MMPort *self)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ MMPortPrivate *priv = MM_PORT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ /* Construct only */
+ priv->device = g_value_dup_string (value);
+ break;
+ case PROP_SUBSYS:
+ /* Construct only */
+ priv->subsys = g_value_get_uint (value);
+ break;
+ case PROP_TYPE:
+ /* Construct only */
+ priv->ptype = g_value_get_uint (value);
+ break;
+ case PROP_CARRIER_DETECT:
+ priv->carrier_detect = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ MMPortPrivate *priv = MM_PORT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, priv->device);
+ break;
+ case PROP_SUBSYS:
+ g_value_set_uint (value, priv->subsys);
+ break;
+ case PROP_TYPE:
+ g_value_set_uint (value, priv->ptype);
+ break;
+ case PROP_CARRIER_DETECT:
+ g_value_set_boolean (value, priv->carrier_detect);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+finalize (GObject *object)
+{
+ MMPortPrivate *priv = MM_PORT_GET_PRIVATE (object);
+
+ g_free (priv->device);
+
+ G_OBJECT_CLASS (mm_port_parent_class)->finalize (object);
+}
+
+static void
+mm_port_class_init (MMPortClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMPortPrivate));
+
+ /* Virtual methods */
+ object_class->constructor = constructor;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+
+ g_object_class_install_property
+ (object_class, PROP_DEVICE,
+ g_param_spec_string (MM_PORT_DEVICE,
+ "Device",
+ "Device",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, PROP_SUBSYS,
+ g_param_spec_uint (MM_PORT_SUBSYS,
+ "Subsystem",
+ "Subsystem",
+ MM_PORT_SUBSYS_UNKNOWN,
+ MM_PORT_SUBSYS_LAST,
+ MM_PORT_SUBSYS_UNKNOWN,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, PROP_TYPE,
+ g_param_spec_uint (MM_PORT_TYPE,
+ "Type",
+ "Type",
+ MM_PORT_TYPE_UNKNOWN,
+ MM_PORT_TYPE_LAST,
+ MM_PORT_TYPE_UNKNOWN,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, PROP_CARRIER_DETECT,
+ g_param_spec_boolean (MM_PORT_CARRIER_DETECT,
+ "Carrier Detect",
+ "Has Carrier Detect",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
diff --git a/src/mm-port.h b/src/mm-port.h
new file mode 100644
index 00000000..339b91ea
--- /dev/null
+++ b/src/mm-port.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_PORT_H
+#define MM_PORT_H
+
+#include <glib.h>
+#include <glib/gtypes.h>
+#include <glib-object.h>
+
+typedef enum {
+ MM_PORT_SUBSYS_UNKNOWN = 0x0,
+ MM_PORT_SUBSYS_TTY,
+ MM_PORT_SUBSYS_NET,
+
+ MM_PORT_SUBSYS_LAST = MM_PORT_SUBSYS_NET
+} MMPortSubsys;
+
+typedef enum {
+ MM_PORT_TYPE_UNKNOWN = 0x0,
+ MM_PORT_TYPE_PRIMARY,
+ MM_PORT_TYPE_SECONDARY,
+ MM_PORT_TYPE_IGNORED,
+
+ MM_PORT_TYPE_LAST = MM_PORT_TYPE_IGNORED
+} MMPortType;
+
+#define MM_TYPE_PORT (mm_port_get_type ())
+#define MM_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PORT, MMPort))
+#define MM_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PORT, MMPortClass))
+#define MM_IS_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PORT))
+#define MM_IS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PORT))
+#define MM_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PORT, MMPortClass))
+
+#define MM_PORT_DEVICE "device"
+#define MM_PORT_SUBSYS "subsys"
+#define MM_PORT_TYPE "type"
+#define MM_PORT_CARRIER_DETECT "carrier-detect"
+
+typedef struct _MMPort MMPort;
+typedef struct _MMPortClass MMPortClass;
+
+struct _MMPort {
+ GObject parent;
+};
+
+struct _MMPortClass {
+ GObjectClass parent;
+};
+
+GType mm_port_get_type (void);
+
+const char * mm_port_get_device (MMPort *self);
+
+MMPortSubsys mm_port_get_subsys (MMPort *self);
+
+MMPortType mm_port_get_port_type (MMPort *self);
+
+gboolean mm_port_get_carrier_detect (MMPort *self);
+
+#endif /* MM_PORT_H */
+
diff --git a/src/mm-serial-parsers.c b/src/mm-serial-parsers.c
index 8e6b75b8..ae0c20da 100644
--- a/src/mm-serial-parsers.c
+++ b/src/mm-serial-parsers.c
@@ -87,6 +87,9 @@ mm_serial_parser_v0_parse (gpointer data,
g_return_val_if_fail (parser != NULL, FALSE);
g_return_val_if_fail (response != NULL, FALSE);
+ if (G_UNLIKELY (!response->len || !strlen (response->str)))
+ return FALSE;
+
found = g_regex_match_full (parser->generic_response, response->str, response->len, 0, 0, &match_info, NULL);
if (found) {
str = g_match_info_fetch (match_info, 1);
@@ -205,7 +208,10 @@ mm_serial_parser_v1_parse (gpointer data,
g_return_val_if_fail (parser != NULL, FALSE);
g_return_val_if_fail (response != NULL, FALSE);
- /* First, check for successfule responses */
+ if (G_UNLIKELY (!response->len || !strlen (response->str)))
+ return FALSE;
+
+ /* First, check for successful responses */
found = g_regex_match_full (parser->regex_ok, response->str, response->len, 0, 0, NULL, NULL);
if (found)
diff --git a/src/mm-serial.c b/src/mm-serial-port.c
index 0301a592..26585e37 100644
--- a/src/mm-serial.c
+++ b/src/mm-serial-port.c
@@ -1,4 +1,18 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
#define _GNU_SOURCE /* for strcasestr() */
@@ -13,30 +27,28 @@
#include <sys/ioctl.h>
#include <string.h>
-#include "mm-serial.h"
+#include "mm-serial-port.h"
#include "mm-errors.h"
#include "mm-options.h"
-static gboolean mm_serial_queue_process (gpointer data);
+static gboolean mm_serial_port_queue_process (gpointer data);
-G_DEFINE_TYPE (MMSerial, mm_serial, G_TYPE_OBJECT)
+G_DEFINE_TYPE (MMSerialPort, mm_serial_port, MM_TYPE_PORT)
enum {
PROP_0,
- PROP_DEVICE,
PROP_BAUD,
PROP_BITS,
PROP_PARITY,
PROP_STOPBITS,
PROP_SEND_DELAY,
- PROP_CARRIER_DETECT,
LAST_PROP
};
#define SERIAL_BUF_SIZE 2048
-#define MM_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_SERIAL, MMSerialPrivate))
+#define MM_SERIAL_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_SERIAL_PORT, MMSerialPortPrivate))
typedef struct {
int fd;
@@ -54,18 +66,16 @@ typedef struct {
struct termios old_t;
- char *device;
guint baud;
guint bits;
char parity;
guint stopbits;
guint64 send_delay;
- gboolean carrier_detect;
guint queue_schedule;
guint watch_id;
guint timeout_id;
-} MMSerialPrivate;
+} MMSerialPortPrivate;
typedef struct {
GRegex *regex;
@@ -74,32 +84,24 @@ typedef struct {
GDestroyNotify notify;
} MMUnsolicitedMsgHandler;
-const char *
-mm_serial_get_device (MMSerial *serial)
-{
- g_return_val_if_fail (MM_IS_SERIAL (serial), NULL);
-
- return MM_SERIAL_GET_PRIVATE (serial)->device;
-}
-
static void
-mm_serial_set_cached_reply (MMSerial *self,
- const char *command,
- const char *reply)
+mm_serial_port_set_cached_reply (MMSerialPort *self,
+ const char *command,
+ const char *reply)
{
if (reply)
- g_hash_table_insert (MM_SERIAL_GET_PRIVATE (self)->reply_cache,
+ g_hash_table_insert (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache,
g_strdup (command),
g_strdup (reply));
else
- g_hash_table_remove (MM_SERIAL_GET_PRIVATE (self)->reply_cache, command);
+ g_hash_table_remove (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command);
}
static const char *
-mm_serial_get_cached_reply (MMSerial *self,
- const char *command)
+mm_serial_port_get_cached_reply (MMSerialPort *self,
+ const char *command)
{
- return (char *) g_hash_table_lookup (MM_SERIAL_GET_PRIVATE (self)->reply_cache, command);
+ return (char *) g_hash_table_lookup (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command);
}
static int
@@ -237,9 +239,9 @@ parse_stopbits (guint i)
}
static gboolean
-config_fd (MMSerial *self)
+config_fd (MMSerialPort *self)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
struct termio stbuf;
int speed;
int bits;
@@ -265,7 +267,8 @@ config_fd (MMSerial *self)
stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits);
if (ioctl (priv->fd, TCSETA, &stbuf) < 0) {
- g_warning ("(%s) cannot control device (errno %d)", priv->device, errno);
+ g_warning ("(%s) cannot control device (errno %d)",
+ mm_port_get_device (MM_PORT (self)), errno);
return FALSE;
}
@@ -273,7 +276,7 @@ config_fd (MMSerial *self)
}
static void
-serial_debug (const char *prefix, const char *buf, int len)
+serial_debug (MMSerialPort *self, const char *prefix, const char *buf, int len)
{
static GString *debug = NULL;
const char *s;
@@ -305,27 +308,27 @@ serial_debug (const char *prefix, const char *buf, int len)
}
g_string_append_c (debug, '\'');
- g_debug ("%s", debug->str);
+ g_debug ("(%s): %s", mm_port_get_device (MM_PORT (self)), debug->str);
g_string_truncate (debug, 0);
}
static gboolean
-mm_serial_send_command (MMSerial *self,
- const char *command,
- GError **error)
+mm_serial_port_send_command (MMSerialPort *self,
+ const char *command,
+ GError **error)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
const char *s;
int status;
int eagain_count = 1000;
- if (priv->fd == 0) {
+ if (priv->fd < 0) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED,
"%s", "Sending command failed: device is not enabled");
return FALSE;
}
- if (mm_serial_is_connected (self)) {
+ if (mm_serial_port_is_connected (self)) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED,
"%s", "Sending command failed: device is connected");
return FALSE;
@@ -337,7 +340,7 @@ mm_serial_send_command (MMSerial *self,
if (command[strlen (command)] != '\r')
g_string_append_c (priv->command, '\r');
- serial_debug ("-->", priv->command->str, -1);
+ serial_debug (self, "-->", priv->command->str, -1);
s = priv->command->str;
while (*s) {
@@ -374,9 +377,9 @@ typedef struct {
} MMQueueData;
static void
-mm_serial_schedule_queue_process (MMSerial *self)
+mm_serial_port_schedule_queue_process (MMSerialPort *self)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
GSource *source;
if (priv->queue_schedule)
@@ -384,16 +387,16 @@ mm_serial_schedule_queue_process (MMSerial *self)
return;
source = g_idle_source_new ();
- g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_queue_process), G_OBJECT (self)));
+ g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_port_queue_process), G_OBJECT (self)));
g_source_attach (source, NULL);
priv->queue_schedule = g_source_get_id (source);
g_source_unref (source);
}
static void
-mm_serial_got_response (MMSerial *self, GError *error)
+mm_serial_port_got_response (MMSerialPort *self, GError *error)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
MMQueueData *info;
if (priv->timeout_id)
@@ -402,7 +405,7 @@ mm_serial_got_response (MMSerial *self, GError *error)
info = (MMQueueData *) g_queue_pop_head (priv->queue);
if (info) {
if (info->cached && !error)
- mm_serial_set_cached_reply (self, info->command, priv->response->str);
+ mm_serial_port_set_cached_reply (self, info->command, priv->response->str);
if (info->callback)
info->callback (self, priv->response, error, info->user_data);
@@ -416,14 +419,14 @@ mm_serial_got_response (MMSerial *self, GError *error)
g_string_truncate (priv->response, 0);
if (!g_queue_is_empty (priv->queue))
- mm_serial_schedule_queue_process (self);
+ mm_serial_port_schedule_queue_process (self);
}
static gboolean
-mm_serial_timed_out (gpointer data)
+mm_serial_port_timed_out (gpointer data)
{
- MMSerial *self = MM_SERIAL (data);
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPort *self = MM_SERIAL_PORT (data);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
GError *error;
priv->timeout_id = 0;
@@ -434,16 +437,16 @@ mm_serial_timed_out (gpointer data)
/* FIXME: This is not completely correct - if the response finally arrives and there's
some other command waiting for response right now, the other command will
get the output of the timed out command. Not sure what to do here. */
- mm_serial_got_response (self, error);
+ mm_serial_port_got_response (self, error);
return FALSE;
}
static gboolean
-mm_serial_queue_process (gpointer data)
+mm_serial_port_queue_process (gpointer data)
{
- MMSerial *self = MM_SERIAL (data);
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPort *self = MM_SERIAL_PORT (data);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
MMQueueData *info;
GError *error = NULL;
@@ -454,41 +457,41 @@ mm_serial_queue_process (gpointer data)
return FALSE;
if (info->cached) {
- const char *cached = mm_serial_get_cached_reply (self, info->command);
+ const char *cached = mm_serial_port_get_cached_reply (self, info->command);
if (cached) {
g_string_append (priv->response, cached);
- mm_serial_got_response (self, NULL);
+ mm_serial_port_got_response (self, NULL);
return FALSE;
}
}
- if (mm_serial_send_command (self, info->command, &error)) {
+ if (mm_serial_port_send_command (self, info->command, &error)) {
GSource *source;
source = g_timeout_source_new (info->timeout);
- g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_timed_out), G_OBJECT (self)));
+ g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_port_timed_out), G_OBJECT (self)));
g_source_attach (source, NULL);
priv->timeout_id = g_source_get_id (source);
g_source_unref (source);
} else {
- mm_serial_got_response (self, error);
+ mm_serial_port_got_response (self, error);
}
return FALSE;
}
void
-mm_serial_add_unsolicited_msg_handler (MMSerial *self,
- GRegex *regex,
- MMSerialUnsolicitedMsgFn callback,
- gpointer user_data,
- GDestroyNotify notify)
+mm_serial_port_add_unsolicited_msg_handler (MMSerialPort *self,
+ GRegex *regex,
+ MMSerialUnsolicitedMsgFn callback,
+ gpointer user_data,
+ GDestroyNotify notify)
{
MMUnsolicitedMsgHandler *handler;
- MMSerialPrivate *priv;
+ MMSerialPortPrivate *priv;
- g_return_if_fail (MM_IS_SERIAL (self));
+ g_return_if_fail (MM_IS_SERIAL_PORT (self));
g_return_if_fail (regex != NULL);
handler = g_slice_new (MMUnsolicitedMsgHandler);
@@ -497,19 +500,19 @@ mm_serial_add_unsolicited_msg_handler (MMSerial *self,
handler->user_data = user_data;
handler->notify = notify;
- priv = MM_SERIAL_GET_PRIVATE (self);
+ priv = MM_SERIAL_PORT_GET_PRIVATE (self);
priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler);
}
void
-mm_serial_set_response_parser (MMSerial *self,
- MMSerialResponseParserFn fn,
- gpointer user_data,
- GDestroyNotify notify)
+mm_serial_port_set_response_parser (MMSerialPort *self,
+ MMSerialResponseParserFn fn,
+ gpointer user_data,
+ GDestroyNotify notify)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
- g_return_if_fail (MM_IS_SERIAL (self));
+ g_return_if_fail (MM_IS_SERIAL_PORT (self));
if (priv->response_parser_notify)
priv->response_parser_notify (priv->response_parser_user_data);
@@ -535,10 +538,10 @@ remove_eval_cb (const GMatchInfo *match_info,
}
static void
-parse_unsolicited_messages (MMSerial *self,
+parse_unsolicited_messages (MMSerialPort *self,
GString *response)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
GSList *iter;
for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) {
@@ -572,11 +575,11 @@ parse_unsolicited_messages (MMSerial *self,
}
static gboolean
-parse_response (MMSerial *self,
+parse_response (MMSerialPort *self,
GString *response,
GError **error)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE);
@@ -590,15 +593,15 @@ data_available (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
- MMSerial *self = MM_SERIAL (data);
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPort *self = MM_SERIAL_PORT (data);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
char buf[SERIAL_BUF_SIZE + 1];
gsize bytes_read;
GIOStatus status;
if (condition & G_IO_HUP) {
g_string_truncate (priv->response, 0);
- mm_serial_close (self);
+ mm_serial_port_close (self);
return FALSE;
}
@@ -617,63 +620,83 @@ data_available (GIOChannel *source,
err = NULL;
}
+ /* If no bytes read, just let g_io_channel wait for more data */
+ if (bytes_read == 0)
+ break;
+
if (bytes_read > 0) {
- serial_debug ("<--", buf, bytes_read);
+ serial_debug (self, "<--", buf, bytes_read);
g_string_append_len (priv->response, buf, bytes_read);
}
/* Make sure the string doesn't grow too long */
if (priv->response->len > SERIAL_BUF_SIZE) {
g_warning ("%s (%s): response buffer filled before repsonse received",
- G_STRFUNC, mm_serial_get_device (self));
+ G_STRFUNC, mm_port_get_device (MM_PORT (self)));
g_string_erase (priv->response, 0, (SERIAL_BUF_SIZE / 2));
}
if (parse_response (self, priv->response, &err))
- mm_serial_got_response (self, err);
+ mm_serial_port_got_response (self, err);
} while (bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
return TRUE;
}
gboolean
-mm_serial_open (MMSerial *self, GError **error)
+mm_serial_port_open (MMSerialPort *self, GError **error)
{
- MMSerialPrivate *priv;
+ MMSerialPortPrivate *priv;
+ char *devfile;
+ const char *device;
- g_return_val_if_fail (MM_IS_SERIAL (self), FALSE);
+ g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
- priv = MM_SERIAL_GET_PRIVATE (self);
+ priv = MM_SERIAL_PORT_GET_PRIVATE (self);
- if (priv->fd)
+ if (priv->fd >= 0)
/* Already open */
return TRUE;
- g_debug ("(%s) opening serial device...", priv->device);
- priv->fd = open (priv->device, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY);
+ device = mm_port_get_device (MM_PORT (self));
+
+ g_message ("(%s) opening serial device...", device);
+ devfile = g_strdup_printf ("/dev/%s", device);
+ priv->fd = open (devfile, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY);
+ g_free (devfile);
if (priv->fd < 0) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED,
- "Could not open serial device %s: %s", priv->device, strerror (errno));
+ "Could not open serial device %s: %s", device, strerror (errno));
+ return FALSE;
+ }
+
+ if (ioctl (priv->fd, TIOCEXCL) < 0) {
+ g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED,
+ "Could not lock serial device %s: %s", device, strerror (errno));
+ close (priv->fd);
+ priv->fd = -1;
return FALSE;
}
if (ioctl (priv->fd, TCGETA, &priv->old_t) < 0) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED,
- "Could not open serial device %s: %s", priv->device, strerror (errno));
+ "Could not open serial device %s: %s", device, strerror (errno));
close (priv->fd);
+ priv->fd = -1;
return FALSE;
}
if (!config_fd (self)) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED,
- "Could not open serial device %s: %s", priv->device, strerror (errno));
+ "Could not open serial device %s: %s", device, strerror (errno));
close (priv->fd);
- priv->fd = 0;
+ priv->fd = -1;
return FALSE;
}
priv->channel = g_io_channel_unix_new (priv->fd);
+ g_io_channel_set_encoding (priv->channel, NULL, NULL);
priv->watch_id = g_io_add_watch (priv->channel,
G_IO_IN | G_IO_ERR | G_IO_HUP,
data_available, self);
@@ -682,16 +705,16 @@ mm_serial_open (MMSerial *self, GError **error)
}
void
-mm_serial_close (MMSerial *self)
+mm_serial_port_close (MMSerialPort *self)
{
- MMSerialPrivate *priv;
+ MMSerialPortPrivate *priv;
- g_return_if_fail (MM_IS_SERIAL (self));
+ g_return_if_fail (MM_IS_SERIAL_PORT (self));
- priv = MM_SERIAL_GET_PRIVATE (self);
+ priv = MM_SERIAL_PORT_GET_PRIVATE (self);
- if (priv->fd) {
- g_message ("Closing device '%s'", priv->device);
+ if (priv->fd >= 0) {
+ g_message ("(%s) closing serial device...", mm_port_get_device (MM_PORT (self)));
if (priv->channel) {
g_source_remove (priv->watch_id);
@@ -702,22 +725,22 @@ mm_serial_close (MMSerial *self)
ioctl (priv->fd, TCSETA, &priv->old_t);
close (priv->fd);
- priv->fd = 0;
+ priv->fd = -1;
}
}
static void
-internal_queue_command (MMSerial *self,
+internal_queue_command (MMSerialPort *self,
const char *command,
gboolean cached,
guint32 timeout_seconds,
MMSerialResponseFn callback,
gpointer user_data)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
MMQueueData *info;
- g_return_if_fail (MM_IS_SERIAL (self));
+ g_return_if_fail (MM_IS_SERIAL_PORT (self));
g_return_if_fail (command != NULL);
info = g_slice_new0 (MMQueueData);
@@ -729,58 +752,60 @@ internal_queue_command (MMSerial *self,
/* Clear the cached value for this command if not asking for cached value */
if (!cached)
- mm_serial_set_cached_reply (self, command, NULL);
+ mm_serial_port_set_cached_reply (self, command, NULL);
g_queue_push_tail (priv->queue, info);
if (g_queue_get_length (priv->queue) == 1)
- mm_serial_schedule_queue_process (self);
+ mm_serial_port_schedule_queue_process (self);
}
void
-mm_serial_queue_command (MMSerial *self,
- const char *command,
- guint32 timeout_seconds,
- MMSerialResponseFn callback,
- gpointer user_data)
+mm_serial_port_queue_command (MMSerialPort *self,
+ const char *command,
+ guint32 timeout_seconds,
+ MMSerialResponseFn callback,
+ gpointer user_data)
{
internal_queue_command (self, command, FALSE, timeout_seconds, callback, user_data);
}
void
-mm_serial_queue_command_cached (MMSerial *self,
- const char *command,
- guint32 timeout_seconds,
- MMSerialResponseFn callback,
- gpointer user_data)
+mm_serial_port_queue_command_cached (MMSerialPort *self,
+ const char *command,
+ guint32 timeout_seconds,
+ MMSerialResponseFn callback,
+ gpointer user_data)
{
internal_queue_command (self, command, TRUE, timeout_seconds, callback, user_data);
}
typedef struct {
- MMSerial *serial;
+ MMSerialPort *port;
speed_t current_speed;
MMSerialFlashFn callback;
gpointer user_data;
} FlashInfo;
static speed_t
-get_speed (MMSerial *self)
+get_speed (MMSerialPort *self)
{
struct termios options;
- tcgetattr (MM_SERIAL_GET_PRIVATE (self)->fd, &options);
+ memset (&options, 0, sizeof (struct termios));
+ tcgetattr (MM_SERIAL_PORT_GET_PRIVATE (self)->fd, &options);
return cfgetospeed (&options);
}
static void
-set_speed (MMSerial *self, speed_t speed)
+set_speed (MMSerialPort *self, speed_t speed)
{
struct termios options;
int fd;
- fd = MM_SERIAL_GET_PRIVATE (self)->fd;
+ fd = MM_SERIAL_PORT_GET_PRIVATE (self)->fd;
+ memset (&options, 0, sizeof (struct termios));
tcgetattr (fd, &options);
cfsetispeed (&options, speed);
@@ -795,7 +820,7 @@ flash_done (gpointer data)
{
FlashInfo *info = (FlashInfo *) data;
- info->callback (info->serial, info->user_data);
+ info->callback (info->port, info->user_data);
g_slice_free (FlashInfo, info);
}
@@ -805,25 +830,25 @@ flash_do (gpointer data)
{
FlashInfo *info = (FlashInfo *) data;
- set_speed (info->serial, info->current_speed);
+ set_speed (info->port, info->current_speed);
return FALSE;
}
guint
-mm_serial_flash (MMSerial *self,
- guint32 flash_time,
- MMSerialFlashFn callback,
- gpointer user_data)
+mm_serial_port_flash (MMSerialPort *self,
+ guint32 flash_time,
+ MMSerialFlashFn callback,
+ gpointer user_data)
{
FlashInfo *info;
guint id;
- g_return_val_if_fail (MM_IS_SERIAL (self), 0);
+ g_return_val_if_fail (MM_IS_SERIAL_PORT (self), 0);
g_return_val_if_fail (callback != NULL, 0);
info = g_slice_new0 (FlashInfo);
- info->serial = self;
+ info->port = self;
info->current_speed = get_speed (self);
info->callback = callback;
info->user_data = user_data;
@@ -840,19 +865,19 @@ mm_serial_flash (MMSerial *self,
}
gboolean
-mm_serial_is_connected (MMSerial *self)
+mm_serial_port_is_connected (MMSerialPort *self)
{
- MMSerialPrivate *priv;
+ MMSerialPortPrivate *priv;
int mcs = 0;
- g_return_val_if_fail (MM_IS_SERIAL (self), FALSE);
+ g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
- priv = MM_SERIAL_GET_PRIVATE (self);
+ priv = MM_SERIAL_PORT_GET_PRIVATE (self);
- if (!priv->carrier_detect)
+ if (!mm_port_get_carrier_detect (MM_PORT (self)))
return FALSE;
- if (priv->fd == 0)
+ if (priv->fd < 0)
return FALSE;
if (ioctl (priv->fd, TIOCMGET, &mcs) < 0)
@@ -863,61 +888,42 @@ mm_serial_is_connected (MMSerial *self)
/*****************************************************************************/
+MMSerialPort *
+mm_serial_port_new (const char *name, MMPortType ptype)
+{
+ return MM_SERIAL_PORT (g_object_new (MM_TYPE_SERIAL_PORT,
+ MM_PORT_DEVICE, name,
+ MM_PORT_SUBSYS, MM_PORT_SUBSYS_TTY,
+ MM_PORT_TYPE, ptype,
+ NULL));
+}
+
static void
-mm_serial_init (MMSerial *self)
+mm_serial_port_init (MMSerialPort *self)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
priv->reply_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ priv->fd = -1;
priv->baud = 57600;
priv->bits = 8;
priv->parity = 'n';
priv->stopbits = 1;
priv->send_delay = 1000;
- priv->carrier_detect = TRUE;
priv->queue = g_queue_new ();
priv->command = g_string_new_len ("AT", SERIAL_BUF_SIZE);
priv->response = g_string_sized_new (SERIAL_BUF_SIZE);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
-{
- GObject *object;
- MMSerialPrivate *priv;
-
- object = G_OBJECT_CLASS (mm_serial_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
-
- priv = MM_SERIAL_GET_PRIVATE (object);
-
- if (!priv->device) {
- g_warning ("No device provided");
- g_object_unref (object);
- return NULL;
- }
-
- return object;
-}
-
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (object);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (object);
switch (prop_id) {
- case PROP_DEVICE:
- /* Construct only */
- priv->device = g_value_dup_string (value);
- break;
case PROP_BAUD:
priv->baud = g_value_get_uint (value);
break;
@@ -933,9 +939,6 @@ set_property (GObject *object, guint prop_id,
case PROP_SEND_DELAY:
priv->send_delay = g_value_get_uint64 (value);
break;
- case PROP_CARRIER_DETECT:
- priv->carrier_detect = g_value_get_boolean (value);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -946,12 +949,9 @@ static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (object);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (object);
switch (prop_id) {
- case PROP_DEVICE:
- g_value_set_string (value, priv->device);
- break;
case PROP_BAUD:
g_value_set_uint (value, priv->baud);
break;
@@ -967,9 +967,6 @@ get_property (GObject *object, guint prop_id,
case PROP_SEND_DELAY:
g_value_set_uint64 (value, priv->send_delay);
break;
- case PROP_CARRIER_DETECT:
- g_value_set_boolean (value, priv->carrier_detect);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -979,16 +976,15 @@ get_property (GObject *object, guint prop_id,
static void
finalize (GObject *object)
{
- MMSerial *self = MM_SERIAL (object);
- MMSerialPrivate *priv = MM_SERIAL_GET_PRIVATE (self);
+ MMSerialPort *self = MM_SERIAL_PORT (object);
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
- mm_serial_close (self);
+ mm_serial_port_close (self);
g_hash_table_destroy (priv->reply_cache);
g_queue_free (priv->queue);
g_string_free (priv->command, TRUE);
g_string_free (priv->response, TRUE);
- g_free (priv->device);
while (priv->unsolicited_msg_handlers) {
MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) priv->unsolicited_msg_handlers->data;
@@ -1005,34 +1001,25 @@ finalize (GObject *object)
if (priv->response_parser_notify)
priv->response_parser_notify (priv->response_parser_user_data);
- G_OBJECT_CLASS (mm_serial_parent_class)->finalize (object);
+ G_OBJECT_CLASS (mm_serial_port_parent_class)->finalize (object);
}
static void
-mm_serial_class_init (MMSerialClass *klass)
+mm_serial_port_class_init (MMSerialPortClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- g_type_class_add_private (object_class, sizeof (MMSerialPrivate));
+ g_type_class_add_private (object_class, sizeof (MMSerialPortPrivate));
/* Virtual methods */
- object_class->constructor = constructor;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
/* Properties */
g_object_class_install_property
- (object_class, PROP_DEVICE,
- g_param_spec_string (MM_SERIAL_DEVICE,
- "Device",
- "Serial device",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property
(object_class, PROP_BAUD,
- g_param_spec_uint (MM_SERIAL_BAUD,
+ g_param_spec_uint (MM_SERIAL_PORT_BAUD,
"Baud",
"Baud rate",
0, G_MAXUINT, 57600,
@@ -1040,7 +1027,7 @@ mm_serial_class_init (MMSerialClass *klass)
g_object_class_install_property
(object_class, PROP_BITS,
- g_param_spec_uint (MM_SERIAL_BITS,
+ g_param_spec_uint (MM_SERIAL_PORT_BITS,
"Bits",
"Bits",
5, 8, 8,
@@ -1048,7 +1035,7 @@ mm_serial_class_init (MMSerialClass *klass)
g_object_class_install_property
(object_class, PROP_PARITY,
- g_param_spec_char (MM_SERIAL_PARITY,
+ g_param_spec_char (MM_SERIAL_PORT_PARITY,
"Parity",
"Parity",
'E', 'o', 'n',
@@ -1056,7 +1043,7 @@ mm_serial_class_init (MMSerialClass *klass)
g_object_class_install_property
(object_class, PROP_STOPBITS,
- g_param_spec_uint (MM_SERIAL_STOPBITS,
+ g_param_spec_uint (MM_SERIAL_PORT_STOPBITS,
"Stopbits",
"Stopbits",
1, 2, 1,
@@ -1064,17 +1051,9 @@ mm_serial_class_init (MMSerialClass *klass)
g_object_class_install_property
(object_class, PROP_SEND_DELAY,
- g_param_spec_uint64 (MM_SERIAL_SEND_DELAY,
+ g_param_spec_uint64 (MM_SERIAL_PORT_SEND_DELAY,
"SendDelay",
"Send delay",
0, G_MAXUINT64, 0,
G_PARAM_READWRITE));
-
- g_object_class_install_property
- (object_class, PROP_CARRIER_DETECT,
- g_param_spec_boolean (MM_SERIAL_CARRIER_DETECT,
- "CarrierDetect",
- "Has carrier detect",
- TRUE,
- G_PARAM_READWRITE));
}
diff --git a/src/mm-serial-port.h b/src/mm-serial-port.h
new file mode 100644
index 00000000..0f4497a2
--- /dev/null
+++ b/src/mm-serial-port.h
@@ -0,0 +1,105 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef MM_SERIAL_PORT_H
+#define MM_SERIAL_PORT_H
+
+#include <glib.h>
+#include <glib/gtypes.h>
+#include <glib-object.h>
+
+#include "mm-port.h"
+
+#define MM_TYPE_SERIAL_PORT (mm_serial_port_get_type ())
+#define MM_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SERIAL_PORT, MMSerialPort))
+#define MM_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SERIAL_PORT, MMSerialPortClass))
+#define MM_IS_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SERIAL_PORT))
+#define MM_IS_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SERIAL_PORT))
+#define MM_SERIAL_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SERIAL_PORT, MMSerialPortClass))
+
+#define MM_SERIAL_PORT_BAUD "baud"
+#define MM_SERIAL_PORT_BITS "bits"
+#define MM_SERIAL_PORT_PARITY "parity"
+#define MM_SERIAL_PORT_STOPBITS "stopbits"
+#define MM_SERIAL_PORT_SEND_DELAY "send-delay"
+
+typedef struct _MMSerialPort MMSerialPort;
+typedef struct _MMSerialPortClass MMSerialPortClass;
+
+typedef gboolean (*MMSerialResponseParserFn) (gpointer user_data,
+ GString *response,
+ GError **error);
+
+typedef void (*MMSerialUnsolicitedMsgFn) (MMSerialPort *port,
+ GMatchInfo *match_info,
+ gpointer user_data);
+
+typedef void (*MMSerialResponseFn) (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data);
+
+typedef void (*MMSerialFlashFn) (MMSerialPort *port,
+ gpointer user_data);
+
+struct _MMSerialPort {
+ MMPort parent;
+};
+
+struct _MMSerialPortClass {
+ MMPortClass parent;
+};
+
+GType mm_serial_port_get_type (void);
+
+MMSerialPort *mm_serial_port_new (const char *name, MMPortType ptype);
+
+void mm_serial_port_add_unsolicited_msg_handler (MMSerialPort *self,
+ GRegex *regex,
+ MMSerialUnsolicitedMsgFn callback,
+ gpointer user_data,
+ GDestroyNotify notify);
+
+void mm_serial_port_set_response_parser (MMSerialPort *self,
+ MMSerialResponseParserFn fn,
+ gpointer user_data,
+ GDestroyNotify notify);
+
+gboolean mm_serial_port_open (MMSerialPort *self,
+ GError **error);
+
+void mm_serial_port_close (MMSerialPort *self);
+void mm_serial_port_queue_command (MMSerialPort *self,
+ const char *command,
+ guint32 timeout_seconds,
+ MMSerialResponseFn callback,
+ gpointer user_data);
+
+void mm_serial_port_queue_command_cached (MMSerialPort *self,
+ const char *command,
+ guint32 timeout_seconds,
+ MMSerialResponseFn callback,
+ gpointer user_data);
+
+guint mm_serial_port_flash (MMSerialPort *self,
+ guint32 flash_time,
+ MMSerialFlashFn callback,
+ gpointer user_data);
+
+gboolean mm_serial_port_is_connected (MMSerialPort *self);
+
+#endif /* MM_SERIAL_PORT_H */
+
diff --git a/src/mm-serial.h b/src/mm-serial.h
deleted file mode 100644
index e3479eed..00000000
--- a/src/mm-serial.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-
-#ifndef MM_SERIAL_H
-#define MM_SERIAL_H
-
-#include <glib.h>
-#include <glib/gtypes.h>
-#include <glib-object.h>
-
-#define MM_TYPE_SERIAL (mm_serial_get_type ())
-#define MM_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SERIAL, MMSerial))
-#define MM_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SERIAL, MMSerialClass))
-#define MM_IS_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SERIAL))
-#define MM_IS_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SERIAL))
-#define MM_SERIAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SERIAL, MMSerialClass))
-
-#define MM_SERIAL_DEVICE "serial-device"
-#define MM_SERIAL_BAUD "baud"
-#define MM_SERIAL_BITS "bits"
-#define MM_SERIAL_PARITY "parity"
-#define MM_SERIAL_STOPBITS "stopbits"
-#define MM_SERIAL_SEND_DELAY "send-delay"
-#define MM_SERIAL_CARRIER_DETECT "carrier-detect"
-
-typedef struct _MMSerial MMSerial;
-typedef struct _MMSerialClass MMSerialClass;
-
-typedef gboolean (*MMSerialResponseParserFn) (gpointer user_data,
- GString *response,
- GError **error);
-
-typedef void (*MMSerialUnsolicitedMsgFn) (MMSerial *serial,
- GMatchInfo *match_info,
- gpointer user_data);
-
-typedef void (*MMSerialResponseFn) (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data);
-
-typedef void (*MMSerialFlashFn) (MMSerial *serial,
- gpointer user_data);
-
-struct _MMSerial {
- GObject parent;
-};
-
-struct _MMSerialClass {
- GObjectClass parent;
-};
-
-GType mm_serial_get_type (void);
-
-void mm_serial_add_unsolicited_msg_handler (MMSerial *self,
- GRegex *regex,
- MMSerialUnsolicitedMsgFn callback,
- gpointer user_data,
- GDestroyNotify notify);
-
-void mm_serial_set_response_parser (MMSerial *self,
- MMSerialResponseParserFn fn,
- gpointer user_data,
- GDestroyNotify notify);
-
-gboolean mm_serial_open (MMSerial *self,
- GError **error);
-
-void mm_serial_close (MMSerial *self);
-void mm_serial_queue_command (MMSerial *self,
- const char *command,
- guint32 timeout_seconds,
- MMSerialResponseFn callback,
- gpointer user_data);
-
-void mm_serial_queue_command_cached (MMSerial *self,
- const char *command,
- guint32 timeout_seconds,
- MMSerialResponseFn callback,
- gpointer user_data);
-
-guint mm_serial_flash (MMSerial *self,
- guint32 flash_time,
- MMSerialFlashFn callback,
- gpointer user_data);
-
-gboolean mm_serial_is_connected (MMSerial *self);
-const char *mm_serial_get_device (MMSerial *self);
-
-#endif /* MM_SERIAL_H */
diff --git a/test/mm-test.py b/test/mm-test.py
index f4eacfeb..a5389672 100755
--- a/test/mm-test.py
+++ b/test/mm-test.py
@@ -8,10 +8,32 @@ MM_DBUS_SERVICE='org.freedesktop.ModemManager'
MM_DBUS_PATH='/org/freedesktop/ModemManager'
MM_DBUS_INTERFACE='org.freedesktop.ModemManager'
MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
+MM_DBUS_INTERFACE_MODEM_CDMA='org.freedesktop.ModemManager.Modem.Cdma'
MM_DBUS_INTERFACE_MODEM_GSM_CARD='org.freedesktop.ModemManager.Modem.Gsm.Card'
MM_DBUS_INTERFACE_MODEM_GSM_NETWORK='org.freedesktop.ModemManager.Modem.Gsm.Network'
-def get_network_mode(modem):
+def get_cdma_band_class(band_class):
+ if band_class == 1:
+ return "800MHz"
+ elif band_class == 2:
+ return "1900MHz"
+ else:
+ return "Unknown"
+
+def inspect_cdma(proxy):
+ cdma = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_CDMA)
+ try:
+ print "ESN: %s" % cdma.GetEsn()
+ except dbus.exceptions.DBusException:
+ pass
+ print "-------------------"
+ info = cdma.GetServingSystem()
+ print "Class: %s" % get_cdma_band_class(info[0])
+ print "Band: %s" % info[1]
+ print "SID: %d" % info[2]
+
+
+def get_gsm_network_mode(modem):
mode = modem.GetNetworkMode()
if mode == 1:
mode = "GPRS"
@@ -26,7 +48,7 @@ def get_network_mode(modem):
print "Mode: %s" % mode
-def get_band(modem):
+def get_gsm_band(modem):
band = modem.GetBand()
if band == 0:
band = "Any"
@@ -58,6 +80,38 @@ def get_band(modem):
print "Band: %s" % band
+def inspect_gsm(proxy):
+ # Gsm.Card interface
+ card = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_CARD)
+ try:
+ print "IMEI: %s" % card.GetImei()
+ except dbus.exceptions.DBusException:
+ pass
+ print "IMSI: %s" % card.GetImsi()
+
+ # Gsm.Network interface
+ net = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_NETWORK)
+ print "Signal quality: %d" % net.GetSignalQuality()
+
+ print "Scanning..."
+ results = net.Scan()
+ for r in results:
+ status = r['status']
+ if status == "1":
+ status = "available"
+ elif status == "2":
+ status = "current"
+ elif status == "3":
+ status = "forbidden"
+ else:
+ status = "(Unknown)"
+
+ if len(r['operator-long']):
+ print "%s: %s" % (r['operator-long'], status)
+ else:
+ print "%s: %s" % (r['operator-short'], status)
+
+
bus = dbus.SystemBus()
# Get available modems:
@@ -84,42 +138,22 @@ for m in modems:
print "Invalid modem type: %d" % type
print "Driver: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Driver'))
- print "Data device: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'DataDevice'))
+ print "Modem device: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'MasterDevice'))
+ print "Data device: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Device'))
# Modem interface
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
modem.Enable(True)
- if type != 1:
- continue
-
- # Gsm.Card interface
- card = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_CARD)
- print "IMEI: %s" % card.GetImei()
- print "IMSI: %s" % card.GetImsi()
-
- info = card.GetInfo()
- print "Vendor: '%s' Model: '%s' Version: '%s'" % info
-
- # Gsm.Network interface
- net = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_NETWORK)
- print "Signal quality: %d" % net.GetSignalQuality()
-
- print "Scanning..."
- results = net.Scan()
- for r in results:
- status = r['status']
- if status == "1":
- status = "available"
- elif status == "2":
- status = "current"
- elif status == "3":
- status = "forbidden"
- else:
- status = "(Unknown)"
-
- print "%s: %s" % (r['operator-long'], status)
+ info = modem.GetInfo()
+ print "Vendor: %s" % info[0]
+ print "Model: %s" % info[1]
+ print "Version: %s" % info[2]
+ if type == 1:
+ inspect_gsm(proxy)
+ elif type == 2:
+ inspect_cdma(proxy)
print
modem.Enable(False)