udev: move device probing and detection to udev

Get rid of dependency on HAL, using libgudev instead.  Fix up the plugin API
to no longer use either HAL or udev defines, but let plugins use whatever
mechanism they want for getting more information out of the device given the
subsystem and device node name.

Modems are now defined as "master" devices which "own" a one or more ports.
A port could be a serial tty device or a network device or whatever.  The
plugin figures out whether it supports a given port or not and then assigns
it to a new or existing modem.  Modems now have a 'valid' property that
should be set to TRUE when the modem has enough ports to operate correctly.
For devices (ex. 'hso') that use a network device for data transfer, the
modem would need to grab at least one TTY and the network device associated
with that physical device to be 'valid'.

Also move the generic modem support code to a plugin like other modem plugins,
and change the I-support-this-device mechanism to return a number indicating
the level of support.  For example, the generic plugin would return a quite
low number if the device indicates via probing that it can do GSM or CDMA, but
a more specific plugin can indicate better support for the device, and thus
the more specific plugin would win control.
This commit is contained in:
Dan Williams
2009-06-18 14:25:30 -04:00
parent 0555cc1824
commit 924814c101
27 changed files with 3279 additions and 1597 deletions
+13 -9
View File
@@ -2,27 +2,35 @@ 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-serial.c \
mm-serial.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 \
@@ -36,11 +44,7 @@ modem_manager_SOURCES = \
mm-options.c \
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.h
mm-manager-glue.h: $(top_srcdir)/introspection/mm-manager.xml
dbus-binding-tool --prefix=mm_manager --mode=glib-server --output=$@ $<
+4 -89
View File
@@ -5,7 +5,6 @@
#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"
@@ -135,87 +134,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
@@ -249,21 +172,13 @@ 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);
g_main_loop_run (loop);
hal_deinit (manager);
g_object_unref (manager);
g_object_unref (proxy);
dbus_g_connection_unref (bus);
+182 -35
View File
@@ -16,25 +16,124 @@ 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;
} 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 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)
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)
{
MMGenericCdma *self = MM_GENERIC_CDMA (modem);
if (strcmp (subsys, "tty"))
return FALSE;
return !!mm_serial_get_port (MM_SERIAL (self), name);
}
static gboolean
grab_port (MMModem *modem,
const char *subsys,
const char *name,
GError **error)
{
MMGenericCdma *self = MM_GENERIC_CDMA (modem);
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self);
MMSerialPortType ptype = MM_SERIAL_PORT_TYPE_IGNORED;
MMSerialPort *port;
if (strcmp (subsys, "tty"))
return FALSE;
if (!priv->primary)
ptype = MM_SERIAL_PORT_TYPE_PRIMARY;
else if (!priv->secondary)
ptype = MM_SERIAL_PORT_TYPE_SECONDARY;
port = mm_serial_add_port (MM_SERIAL (self), name, ptype);
g_object_set (G_OBJECT (port), MM_SERIAL_PORT_CARRIER_DETECT, FALSE, NULL);
mm_serial_port_set_response_parser (port,
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
if (ptype == MM_SERIAL_PORT_TYPE_PRIMARY) {
priv->primary = port;
g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
check_valid (self);
} else if (ptype == MM_SERIAL_PORT_TYPE_SECONDARY)
priv->secondary = port;
return TRUE;
}
static void
release_port (MMModem *modem, const char *subsys, const char *name)
{
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMSerialPort *port;
if (strcmp (subsys, "tty"))
return;
port = mm_serial_get_port (MM_SERIAL (modem), name);
if (!port)
return;
if (port == priv->primary) {
mm_serial_remove_port (MM_SERIAL (modem), port);
priv->primary = NULL;
}
if (port == priv->secondary) {
mm_serial_remove_port (MM_SERIAL (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 +148,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 +164,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 +180,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 +218,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 +239,17 @@ 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
get_signal_quality_done (MMSerial *serial,
get_signal_quality_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -182,10 +286,15 @@ 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);
}
/*****************************************************************************/
@@ -261,6 +370,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 +378,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,6 +450,9 @@ 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;
@@ -361,24 +474,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 +511,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->primary)
g_value_set_string (value, mm_serial_port_get_device (priv->primary));
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,13 +569,21 @@ 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);
@@ -448,6 +591,10 @@ mm_generic_cdma_class_init (MMGenericCdmaClass *klass)
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
+9 -8
View File
@@ -6,12 +6,12 @@
#include "mm-modem.h"
#include "mm-serial.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;
@@ -23,7 +23,8 @@ typedef struct {
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 */
+325 -132
View File
@@ -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,39 @@ typedef struct {
guint32 signal_quality;
guint32 cid;
MMSerialPort *primary;
MMSerialPort *secondary;
} 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 +120,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 +135,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 +169,113 @@ 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)
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)
{
MMGenericGsm *self = MM_GENERIC_GSM (modem);
if (strcmp (subsys, "tty"))
return FALSE;
return !!mm_serial_get_port (MM_SERIAL (self), name);
}
static gboolean
grab_port (MMModem *modem,
const char *subsys,
const char *name,
GError **error)
{
MMGenericGsm *self = MM_GENERIC_GSM (modem);
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
MMSerialPortType ptype = MM_SERIAL_PORT_TYPE_IGNORED;
MMSerialPort *port;
GRegex *regex;
if (strcmp (subsys, "tty"))
return FALSE;
if (!priv->primary)
ptype = MM_SERIAL_PORT_TYPE_PRIMARY;
else if (!priv->secondary)
ptype = MM_SERIAL_PORT_TYPE_SECONDARY;
port = mm_serial_add_port (MM_SERIAL (self), name, ptype);
mm_serial_port_set_response_parser (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 (port, regex, reg_state_changed, self, NULL);
g_regex_unref (regex);
if (ptype == MM_SERIAL_PORT_TYPE_PRIMARY) {
priv->primary = port;
g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
check_valid (self);
} else if (ptype == MM_SERIAL_PORT_TYPE_SECONDARY)
priv->secondary = port;
return TRUE;
}
static void
release_port (MMModem *modem, const char *subsys, const char *name)
{
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
MMSerialPort *port;
if (strcmp (subsys, "tty"))
return;
port = mm_serial_get_port (MM_SERIAL (modem), name);
if (!port)
return;
if (port == priv->primary) {
mm_serial_remove_port (MM_SERIAL (modem), port);
priv->primary = NULL;
check_valid (MM_GENERIC_GSM (modem));
}
if (port == priv->secondary) {
mm_serial_remove_port (MM_SERIAL (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,7 +289,7 @@ enable_done (MMSerial *serial,
}
static void
init_done (MMSerial *serial,
init_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -186,35 +300,35 @@ init_done (MMSerial *serial,
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);
mm_serial_port_queue_command (port, "+CFUN=1", 5, enable_done, user_data);
}
}
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_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
@@ -223,6 +337,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 +348,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 +362,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 +382,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,10 +394,11 @@ 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
@@ -297,7 +414,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 +430,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 +444,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)
@@ -345,21 +462,21 @@ get_card_info (MMModemGsmCard *modem,
MMModemGsmCardInfoFn 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,
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 +495,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 +524,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 +554,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 +584,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 +621,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 */
@@ -618,24 +757,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_registration)
get_registration_status (MM_SERIAL (info->modem), info);
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
if (priv->pending_registration)
get_registration_status (priv->primary, info);
return FALSE;
}
@@ -647,13 +789,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;
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (serial);
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
if (error) {
info->error = g_error_copy (error);
@@ -666,7 +808,7 @@ get_reg_status_done (MMSerial *serial,
int unsolicited, stat;
if (sscanf (response->str + 7, "%d,%d", &unsolicited, &stat)) {
reg_status_updated (MM_GENERIC_GSM (serial), stat);
reg_status_updated (MM_GENERIC_GSM (info->modem), stat);
if (!unsolicited && priv->pending_registration) {
guint id;
@@ -687,19 +829,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 void
@@ -708,12 +850,13 @@ do_register (MMModemGsmNetwork *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);
MM_GENERIC_GSM_GET_PRIVATE (modem)->pending_registration =
priv->pending_registration =
g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 60,
pending_registration_timed_out,
info,
@@ -724,7 +867,7 @@ do_register (MMModemGsmNetwork *modem,
else
command = g_strdup ("+COPS=0,,");
mm_serial_queue_command (MM_SERIAL (modem), command, 5, register_done, info);
mm_serial_port_queue_command (priv->primary, command, 5, register_done, info);
g_free (command);
}
@@ -758,7 +901,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)
@@ -774,17 +917,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);
@@ -796,6 +941,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));
@@ -816,12 +962,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);
}
@@ -831,13 +977,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
@@ -861,7 +1008,7 @@ destroy_scan_data (gpointer data)
}
static void
scan_done (MMSerial *serial,
scan_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -880,8 +1027,13 @@ scan_done (MMSerial *serial,
reply += 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)
*/
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);
@@ -922,6 +1074,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),
@@ -929,13 +1082,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)
@@ -945,14 +1098,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)
@@ -1012,13 +1165,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)
@@ -1051,7 +1204,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;
}
@@ -1083,7 +1236,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
@@ -1092,23 +1245,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;
@@ -1127,7 +1282,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,
@@ -1142,23 +1298,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)
@@ -1181,16 +1340,33 @@ 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);
}
@@ -1441,6 +1617,9 @@ 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;
@@ -1484,16 +1663,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
@@ -1507,16 +1676,20 @@ 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:
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1530,21 +1703,30 @@ 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->primary)
g_value_set_string (value, mm_serial_port_get_device (priv->primary));
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;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1581,13 +1763,21 @@ 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);
@@ -1596,6 +1786,9 @@ 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);
}
GType
+9 -8
View File
@@ -6,12 +6,12 @@
#include "mm-modem-gsm-network.h"
#include "mm-serial.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_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;
@@ -23,8 +23,9 @@ typedef struct {
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);
+164 -210
View File
@@ -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,9 +29,11 @@ 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;
} MMManagerPrivate;
@@ -147,169 +149,78 @@ mm_manager_new (DBusGConnection *bus)
return manager;
}
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;
}
static MMModem *
create_generic_modem (MMManager *manager, const char *udi)
static void
remove_modem (MMManager *manager, MMModem *modem)
{
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;
char *device;
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);
device = mm_modem_get_device (modem);
g_assert (device);
g_debug ("Removed modem %s", device);
if (!type_gsm && !type_cdma)
return NULL;
serial_device = libhal_device_get_property_string (priv->hal_ctx, udi, "serial.device", NULL);
g_return_val_if_fail (serial_device != NULL, NULL);
driver = get_driver_name (priv->hal_ctx, udi);
g_return_val_if_fail (driver != NULL, NULL);
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_REMOVED], 0, modem);
g_hash_table_remove (priv->modems, device);
g_free (device);
}
static void
add_modem (MMManager *manager, const char *udi, MMModem *modem)
modem_valid (MMModem *modem, GParamSpec *pspec, gpointer user_data)
{
MMManager *manager = MM_MANAGER (user_data);
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
static guint32 id = 0;
char *path, *device;
g_hash_table_insert (priv->modems, g_strdup (udi), modem);
dbus_g_connection_register_g_object (priv->connection, udi, G_OBJECT (modem));
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);
g_signal_emit (manager, signals[DEVICE_ADDED], 0, modem);
}
device = mm_modem_get_device (modem);
g_assert (device);
g_debug ("Exported modem %s", device);
g_free (device);
static MMModem *
modem_exists (MMManager *manager, const char *udi)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
return (MMModem *) g_hash_table_lookup (priv->modems, udi);
g_signal_emit (manager, signals[DEVICE_ADDED], 0, modem);
} else
remove_modem (manager, modem);
}
static void
create_initial_modems_from_plugins (MMManager *manager)
add_modem (MMManager *manager, MMModem *modem)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
GSList *iter;
char *device;
gboolean valid = FALSE;
for (iter = priv->plugins; iter; iter = iter->next) {
MMPlugin *plugin = MM_PLUGIN (iter->data);
char **udis;
int i;
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 (modem_exists (manager, udi)) {
g_warning ("Modem for UDI %s already exists, ignoring", udi);
continue;
}
modem = mm_plugin_create_modem (plugin, priv->hal_ctx, udi);
if (modem)
add_modem (manager, udi, modem);
}
g_strfreev (udis);
}
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);
}
}
static void
create_initial_modems_generic (MMManager *manager)
{
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);
}
if (devices) {
for (i = 0; i < num_devices; i++) {
char *udi = devices[i];
MMModem *modem;
if (modem_exists (manager, udi))
/* Already exists, most likely handled by a plugin */
continue;
modem = create_generic_modem (manager, udi);
if (modem)
add_modem (manager, g_strdup (udi), modem);
}
}
g_strfreev (devices);
}
static void
create_initial_modems (MMManager *manager)
{
create_initial_modems_from_plugins (manager);
create_initial_modems_generic (manager);
g_free (device);
}
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_ptr_array_add (*devices, g_strdup ((char *) key));
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 gboolean
@@ -325,118 +236,164 @@ impl_manager_enumerate_devices (MMManager *manager,
return TRUE;
}
typedef struct {
MMModem *modem;
const char *subsys;
const char *name;
} FindPortInfo;
static void
device_added (LibHalContext *ctx, const char *udi)
find_port (gpointer key, gpointer data, gpointer user_data)
{
FindPortInfo *info = user_data;
MMModem *modem = MM_MODEM (data);
if (!info->modem && mm_modem_owns_port (modem, info->subsys, info->name))
info->modem = modem;
}
static MMModem *
find_modem_for_port (MMManager *manager, const char *subsys, const char *name)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
FindPortInfo info = { NULL, subsys, name };
g_hash_table_foreach (priv->modems, find_port, &info);
return info.modem;
}
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;
MMPlugin *best_plugin = NULL;
guint32 best_level = 0;
GError *error = NULL;
if (modem_exists (manager, udi))
/* Shouldn't happen */
g_return_if_fail (device != NULL);
subsys = g_udev_device_get_subsystem (device);
name = g_udev_device_get_name (device);
if (find_modem_for_port (manager, subsys, name))
return;
for (iter = priv->plugins; iter && modem == NULL; iter = iter->next) {
/* Build up the list of plugins that support this port */
for (iter = priv->plugins; iter; iter = iter->next) {
MMPlugin *plugin = MM_PLUGIN (iter->data);
guint32 level;
if (mm_plugin_supports_udi (plugin, ctx, udi)) {
modem = mm_plugin_create_modem (plugin, ctx, udi);
if (modem)
break;
level = mm_plugin_supports_port (plugin, subsys, name);
if (level > best_level) {
best_plugin = plugin;
best_level = level;
}
}
if (!modem)
/* None of the plugins supported the udi, try generic devices */
modem = create_generic_modem (manager, udi);
/* Let the best plugin handle this port */
if (!best_plugin)
return;
if (modem)
add_modem (manager, udi, modem);
}
static void
device_removed (LibHalContext *ctx, const char *udi)
{
MMManager *manager = MM_MANAGER (libhal_ctx_get_user_data (ctx));
MMModem *modem;
modem = modem_exists (manager, udi);
modem = mm_plugin_grab_port (best_plugin, subsys, name, &error);
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);
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 (best_plugin),
type_name,
mm_modem_get_device (modem),
name);
} else {
g_warning ("%s: plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
__func__, mm_plugin_get_name (best_plugin), subsys, name,
error ? error->code : -1,
(error && error->message) ? error->message : "(unknown)");
return;
}
add_modem (manager, modem);
}
static void
device_new_capability (LibHalContext *ctx, const char *udi, const char *capability)
device_removed (MMManager *manager, GUdevDevice *device)
{
device_added (ctx, udi);
MMModem *modem;
const char *subsys, *name;
g_return_if_fail (device != NULL);
subsys = g_udev_device_get_subsystem (device);
name = g_udev_device_get_name (device);
modem = find_modem_for_port (manager, subsys, name);
if (modem)
mm_modem_release_port (modem, subsys, name);
}
DBusGConnection *
mm_manager_get_bus (MMManager *manager)
static void
handle_uevent (GUdevClient *client,
const char *action,
GUdevDevice *device,
gpointer user_data)
{
g_return_val_if_fail (MM_IS_MANAGER (manager), NULL);
MMManager *self = MM_MANAGER (user_data);
const char *subsys;
return MM_MANAGER_GET_PRIVATE (manager)->connection;
}
g_return_if_fail (action != NULL);
static gboolean
remove_one (gpointer key,
gpointer value,
gpointer user_data)
{
const char *udi = (char *) key;
MMModem *modem = MM_MODEM (value);
MMManager *manager = MM_MANAGER (user_data);
/* A bit paranoid */
subsys = g_udev_device_get_subsystem (device);
g_return_if_fail (subsys != NULL);
g_debug ("Removed modem %s", udi);
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
g_return_if_fail (!strcmp (subsys, "tty") || !strcmp (subsys, "net"));
return TRUE;
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->udev = g_udev_client_new (subsys);
g_assert (priv->udev);
g_signal_connect (priv->udev, "uevent", G_CALLBACK (handle_uevent), manager);
}
static void
@@ -449,11 +406,8 @@ finalize (GObject *object)
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);
+1 -5
View File
@@ -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 */
+95 -2
View File
@@ -197,6 +197,75 @@ impl_modem_disconnect (MMModem *modem,
}
/*****************************************************************************/
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,
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, 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;
}
/*****************************************************************************/
static void
@@ -210,9 +279,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));
@@ -224,6 +301,14 @@ mm_modem_init (gpointer g_iface)
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
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,
@@ -242,6 +327,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;
}
+45 -7
View File
@@ -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_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_GSM 1
#define MM_MODEM_TYPE_CDMA 2
#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;
@@ -57,6 +64,19 @@ 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,
GError **error);
void (*release_port) (MMModem *self,
const char *subsys,
const char *name);
void (*enable) (MMModem *self,
gboolean enable,
MMModemFn callback,
@@ -78,6 +98,19 @@ struct _MMModem {
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,
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 +129,9 @@ void mm_modem_disconnect (MMModem *self,
MMModemFn callback,
gpointer user_data);
gboolean mm_modem_get_valid (MMModem *self);
char *mm_modem_get_device (MMModem *self);
#endif /* MM_MODEM_H */
+15 -33
View File
@@ -10,49 +10,31 @@ 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)
{
g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL);
g_return_val_if_fail (hal_ctx != NULL, NULL);
return MM_PLUGIN_GET_INTERFACE (plugin)->list_supported_udis (plugin, hal_ctx);
}
gboolean
mm_plugin_supports_udi (MMPlugin *plugin,
LibHalContext *hal_ctx,
const char *udi)
guint32
mm_plugin_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_val_if_fail (subsys != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
return MM_PLUGIN_GET_INTERFACE (plugin)->supports_udi (plugin, hal_ctx, udi);
return MM_PLUGIN_GET_INTERFACE (plugin)->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), FALSE);
g_return_val_if_fail (subsys != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
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);
return modem;
return MM_PLUGIN_GET_INTERFACE (plugin)->grab_port (plugin, subsys, name, error);
}
/*****************************************************************************/
static void
+32 -22
View File
@@ -4,10 +4,9 @@
#define MM_PLUGIN_H
#include <glib-object.h>
#include <libhal.h>
#include <mm-modem.h>
#define MM_PLUGIN_MAJOR_VERSION 1
#define MM_PLUGIN_MAJOR_VERSION 2
#define MM_PLUGIN_MINOR_VERSION 0
#define MM_TYPE_PLUGIN (mm_plugin_get_type ())
@@ -23,33 +22,44 @@ struct _MMPlugin {
GTypeInterface g_iface;
/* Methods */
const char *(*get_name) (MMPlugin *self);
const char *(*get_name) (MMPlugin *self);
char **(*list_supported_udis) (MMPlugin *self,
LibHalContext *hal_ctx);
/* Check whether a plugin supports a particular modem port, and what level
* of support the plugin has for the device. The plugin should return a
* value between 0 and 100 inclusive, where 0 means the plugin has no
* support for the device, and 100 means the plugin has full support for the
* device.
*/
guint32 (*supports_port) (MMPlugin *self,
const char *subsys,
const char *name);
gboolean (*supports_udi) (MMPlugin *self,
LibHalContext *hal_ctx,
const char *udi);
MMModem *(*create_modem) (MMPlugin *self,
LibHalContext *hal_ctx,
const char *udi);
/* 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);
guint32 mm_plugin_supports_port (MMPlugin *plugin,
const char *subsys,
const char *name);
gboolean mm_plugin_supports_udi (MMPlugin *plugin,
LibHalContext *hal_ctx,
const char *udi);
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 */
+1107
View File
File diff suppressed because it is too large Load Diff
+114
View File
@@ -0,0 +1,114 @@
/* -*- 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>
typedef enum {
MM_SERIAL_PORT_TYPE_UNKNOWN = 0x0,
MM_SERIAL_PORT_TYPE_PRIMARY,
MM_SERIAL_PORT_TYPE_SECONDARY,
MM_SERIAL_PORT_TYPE_IGNORED
} MMSerialPortType;
#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_DEVICE "serial-device"
#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"
#define MM_SERIAL_PORT_CARRIER_DETECT "carrier-detect"
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 {
GObject parent;
};
struct _MMSerialPortClass {
GObjectClass parent;
};
GType mm_serial_port_get_type (void);
MMSerialPort *mm_serial_port_new (const char *name);
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);
const char *mm_serial_port_get_device (MMSerialPort *self);
#endif /* MM_SERIAL_PORT_H */
+52 -978
View File
File diff suppressed because it is too large Load Diff
+24 -56
View File
@@ -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_SERIAL_H
#define MM_SERIAL_H
@@ -7,6 +21,8 @@
#include <glib/gtypes.h>
#include <glib-object.h>
#include "mm-serial-port.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))
@@ -14,33 +30,9 @@
#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;
};
@@ -51,39 +43,15 @@ struct _MMSerialClass {
GType mm_serial_get_type (void);
void mm_serial_add_unsolicited_msg_handler (MMSerial *self,
GRegex *regex,
MMSerialUnsolicitedMsgFn callback,
gpointer user_data,
GDestroyNotify notify);
MMSerialPort *mm_serial_get_port (MMSerial *self,
const char *name);
void mm_serial_set_response_parser (MMSerial *self,
MMSerialResponseParserFn fn,
gpointer user_data,
GDestroyNotify notify);
MMSerialPort *mm_serial_add_port (MMSerial *self,
const char *name,
MMSerialPortType ptype);
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);
gboolean mm_serial_remove_port (MMSerial *self,
MMSerialPort *port);
#endif /* MM_SERIAL_H */