diff options
Diffstat (limited to 'plugins')
46 files changed, 3392 insertions, 1644 deletions
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); |