diff options
author | Dan Williams <dcbw@redhat.com> | 2009-06-28 14:05:05 -0400 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2009-06-28 14:05:05 -0400 |
commit | 6077763d90b69cfc60b23f383c4529f966facaaf (patch) | |
tree | 81ae20133a6ea116d58ddc2ee86644f4e1c9eb0a /plugins | |
parent | 112f2da19dbe8dcd8f32b998459298e7c1884c67 (diff) |
asynchronous and deferred port detection
Allow plugins to perform asynchronous port detection, and to defer port detection
until later. This moves the prober bits into MMPluginBase so that all plugins
can take adavantage of it only when needed; the probing is not done at udev time.
Furthermore, plugins like Novatel can flip the secondary ports over the AT mode
through deferred detection, by deferring the secondary ports until the main port
has been detected and AT$NWDMAT has been sent.
This commit also finishes the port of the rest of the plugins (except mbm) over
to the new port detection methods and plugin API.
Diffstat (limited to 'plugins')
30 files changed, 1705 insertions, 1720 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 11cdfd0b..3d8f6167 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -4,12 +4,12 @@ pkglib_LTLIBRARIES = \ 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 @@ -120,74 +120,92 @@ libmm_plugin_mbm_la_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 BUILT_SOURCES = \ diff --git a/plugins/mm-modem-hso.c b/plugins/mm-modem-hso.c index 10800184..39c3e42b 100644 --- a/plugins/mm-modem-hso.c +++ b/plugins/mm-modem-hso.c @@ -564,6 +564,7 @@ static gboolean grab_port (MMModem *modem, const char *subsys, const char *name, + gpointer user_data, GError **error) { MMGenericGsm *gsm = MM_GENERIC_GSM (modem); diff --git a/plugins/mm-modem-huawei.c b/plugins/mm-modem-huawei.c index 67d4d812..43ee34d1 100644 --- a/plugins/mm-modem-huawei.c +++ b/plugins/mm-modem-huawei.c @@ -496,10 +496,12 @@ handle_status_change (MMSerialPort *port, /*****************************************************************************/ +/* 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); @@ -531,7 +533,7 @@ grab_port (MMModem *modem, if (usbif == 0) { if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; - } else if (usbif == 1) { + } else if (user_data) { if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } @@ -545,8 +547,6 @@ grab_port (MMModem *modem, if (ptype == MM_PORT_TYPE_SECONDARY) { GRegex *regex; - g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); - 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); 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..d3f12629 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 (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 index e8fdb9ef..fbd99079 100644 --- a/plugins/mm-plugin-generic.c +++ b/plugins/mm-plugin-generic.c @@ -25,291 +25,163 @@ #include <time.h> #include <gmodule.h> -#define G_UDEV_API_IS_SUBJECT_TO_CHANGE -#include <gudev/gudev.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" -static void plugin_init (MMPlugin *plugin_class); - -G_DEFINE_TYPE_EXTENDED (MMPluginGeneric, mm_plugin_generic, MM_TYPE_PLUGIN_BASE, - 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init)) +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; -#define MM_PLUGIN_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_GENERIC, MMPluginGenericPrivate)) - -typedef struct { - GUdevClient *client; -} MMPluginGenericPrivate; - - G_MODULE_EXPORT MMPlugin * mm_plugin_create (void) { - return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_GENERIC, NULL)); + return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_GENERIC, + MM_PLUGIN_BASE_NAME, MM_PLUGIN_GENERIC_NAME, + NULL)); } /*****************************************************************************/ -static char * -get_driver_name (GUdevDevice *device) -{ - GUdevDevice *parent = NULL; - const char *driver; - char *ret; - - driver = g_udev_device_get_driver (device); - if (!driver) { - parent = g_udev_device_get_parent (device); - if (parent) - driver = g_udev_device_get_driver (parent); - } - - if (driver) - ret = g_strdup (driver); - if (parent) - g_object_unref (parent); +#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) - return ret; -} - -static GUdevDevice * -find_physical_device (GUdevDevice *child) +static guint32 +get_level_for_capabilities (guint32 capabilities) { - GUdevDevice *iter, *old = NULL; - const char *bus, *type; - - g_return_val_if_fail (child != NULL, NULL); - - bus = g_udev_device_get_property (child, "ID_BUS"); - if (!bus) - return NULL; - - if (!strcmp (bus, "usb")) { - /* Walk the parents to find the 'usb_device' for this device. */ - iter = g_object_ref (child); - while (iter) { - type = g_udev_device_get_devtype (iter); - if (type && !strcmp (type, "usb_device")) - return iter; - - old = iter; - iter = g_udev_device_get_parent (old); - g_object_unref (old); - } - g_object_unref (child); - } else if (!strcmp (bus, "pci")) { - return g_udev_device_get_parent (child); - } - - // FIXME: pci and pcmcia/cardbus? (like Sierra 850/860) - return NULL; + if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM) + return 5; + if (capabilities & CAP_CDMA) + return 5; + return 0; } -#define PROP_GSM "ID_MM_MODEM_GSM" -#define PROP_CDMA "ID_MM_MODEM_IS707_A" -#define PROP_EVDO1 "ID_MM_MODEM_IS856" -#define PROP_EVDOA "ID_MM_MODEM_IS856_A" - -static GUdevDevice * -get_device_type (MMPlugin *plugin, - const char *subsys, - const char *name, - gboolean *gsm, - gboolean *cdma) +static void +probe_result (MMPluginBase *base, + MMPluginBaseSupportsTask *task, + guint32 capabilities, + gpointer user_data) { - MMPluginGenericPrivate *priv = MM_PLUGIN_GENERIC_GET_PRIVATE (plugin); - GUdevDevice *device; - - g_return_val_if_fail (plugin != NULL, NULL); - g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL); - g_return_val_if_fail (subsys != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - device = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name); - if (!device) - return NULL; - - if (g_udev_device_get_property_as_boolean (device, PROP_GSM)) - *gsm = TRUE; - if ( g_udev_device_get_property_as_boolean (device, PROP_CDMA) - || g_udev_device_get_property_as_boolean (device, PROP_EVDO1) - || g_udev_device_get_property_as_boolean (device, PROP_EVDOA)) - *cdma = TRUE; - - return device; + mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities)); } -static guint32 -supports_port (MMPlugin *plugin, - const char *subsys, - const char *name) +static MMPluginSupportsResult +supports_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task) { - GUdevDevice *device, *physdev = NULL; - gboolean gsm = FALSE, cdma = FALSE; - guint32 level = 0; - - g_return_val_if_fail (plugin != NULL, 0); - g_return_val_if_fail (MM_IS_PLUGIN (plugin), 0); - g_return_val_if_fail (subsys != NULL, 0); - g_return_val_if_fail (name != NULL, 0); + GUdevDevice *port; + guint32 cached = 0, level; /* Can't do anything with non-serial ports */ - if (strcmp (subsys, "tty")) - return 0; - - device = get_device_type (plugin, subsys, name, &gsm, &cdma); - if (!device) - return 0; - - if (!gsm && !cdma) - goto out; + 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; + } - physdev = find_physical_device (device); - if (!physdev) - goto out; - g_object_unref (physdev); - level = 5; + /* Otherwise kick off a probe */ + if (mm_plugin_base_probe_port (base, task, NULL)) + return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS; -out: - return level; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; } static MMModem * -grab_port (MMPlugin *plugin, - const char *subsys, - const char *name, +grab_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task, GError **error) { - MMPluginGeneric *self = MM_PLUGIN_GENERIC (plugin); - GUdevDevice *device = NULL, *physdev = NULL; - const char *devfile, *sysfs_path; - char *driver = NULL; + GUdevDevice *port = NULL, *physdev = NULL; MMModem *modem = NULL; - gboolean gsm = FALSE, cdma = FALSE; - - g_return_val_if_fail (subsys != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - /* Can't do anything with non-serial ports */ - if (strcmp (subsys, "tty")) - return NULL; + const char *name, *subsys, *devfile, *sysfs_path; + guint32 caps; - device = get_device_type (plugin, subsys, name, &gsm, &cdma); - if (!device) { - g_set_error (error, 0, 0, "Could not get port's udev device."); - return NULL; - } + port = mm_plugin_base_supports_task_get_port (task); + g_assert (port); - if (!gsm && !cdma) { - g_set_error (error, 0, 0, "Modem unsupported (not GSM or CDMA)."); - goto out; - } - - physdev = find_physical_device (device); - if (!physdev) { - g_set_error (error, 0, 0, "Could not get ports's physical device."); - goto out; - } - - devfile = g_udev_device_get_device_file (device); + devfile = g_udev_device_get_device_file (port); if (!devfile) { g_set_error (error, 0, 0, "Could not get port's sysfs file."); - goto out; - } - - driver = get_driver_name (device); - if (!driver) { - g_set_error (error, 0, 0, "Could not get port's driver name."); - goto out; + 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."); - goto out; + return NULL; } - modem = mm_plugin_base_find_modem (MM_PLUGIN_BASE (self), sysfs_path); - if (!modem) { - if (gsm) { + 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, - driver, - mm_plugin_get_name (plugin)); - } else if (cdma) { + 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, - driver, - mm_plugin_get_name (plugin)); + 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, error)) { + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) { g_object_unref (modem); - modem = NULL; + return NULL; } } - - if (modem) - mm_plugin_base_add_modem (MM_PLUGIN_BASE (self), modem); } else { - if (gsm || cdma) { - if (!mm_modem_grab_port (modem, subsys, name, error)) - modem = NULL; + if (caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) { + modem = existing; + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) + return NULL; } } -out: - g_free (driver); - g_object_unref (device); - g_object_unref (physdev); return modem; } -static const char * -get_name (MMPlugin *plugin) -{ - return "Generic"; -} - /*****************************************************************************/ static void -plugin_init (MMPlugin *plugin_class) -{ - /* interface implementation */ - plugin_class->get_name = get_name; - plugin_class->supports_port = supports_port; - plugin_class->grab_port = grab_port; -} - -static void mm_plugin_generic_init (MMPluginGeneric *self) { - MMPluginGenericPrivate *priv = MM_PLUGIN_GENERIC_GET_PRIVATE (self); - const char *subsys[2] = { "tty", NULL }; - - priv->client = g_udev_client_new (subsys); + g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL); } static void dispose (GObject *object) { - MMPluginGenericPrivate *priv = MM_PLUGIN_GENERIC_GET_PRIVATE (object); - - g_object_unref (priv->client); } static void mm_plugin_generic_class_init (MMPluginGenericClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMPluginGenericPrivate)); + MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass); object_class->dispose = dispose; + + pb_class->supports_port = supports_port; + pb_class->grab_port = grab_port; } diff --git a/plugins/mm-plugin-gobi.c b/plugins/mm-plugin-gobi.c index 128ba838..6e5bfd9c 100644 --- a/plugins/mm-plugin-gobi.c +++ b/plugins/mm-plugin-gobi.c @@ -23,287 +23,147 @@ #include "mm-modem-gobi-gsm.h" #include "mm-generic-cdma.h" -static void plugin_init (MMPlugin *plugin_class); - -G_DEFINE_TYPE_EXTENDED (MMPluginGobi, mm_plugin_gobi, MM_TYPE_PLUGIN_BASE, - 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init)) +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; -#define MM_PLUGIN_GOBI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_GOBI, MMPluginGobiPrivate)) - -typedef struct { - GUdevClient *client; -} MMPluginGobiPrivate; - - G_MODULE_EXPORT MMPlugin * mm_plugin_create (void) { - return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_GOBI, NULL)); + return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_GOBI, + MM_PLUGIN_BASE_NAME, "Gobi", + NULL)); } /*****************************************************************************/ -static char * -get_driver_name (GUdevDevice *device) -{ - GUdevDevice *parent = NULL; - const char *driver; - char *ret = NULL; - - driver = g_udev_device_get_driver (device); - if (!driver) { - parent = g_udev_device_get_parent (device); - if (parent) - driver = g_udev_device_get_driver (parent); - } - - if (driver) - ret = g_strdup (driver); - if (parent) - g_object_unref (parent); +#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) - return ret; -} - -static GUdevDevice * -find_physical_device (GUdevDevice *child) +static guint32 +get_level_for_capabilities (guint32 capabilities) { - GUdevDevice *iter, *old = NULL; - const char *bus, *type; - - g_return_val_if_fail (child != NULL, NULL); - - bus = g_udev_device_get_property (child, "ID_BUS"); - if (!bus) - return NULL; - - if (strcmp (bus, "usb")) - return NULL; - - /* Walk the parents to find the 'usb_device' for this device. */ - iter = g_object_ref (child); - while (iter) { - type = g_udev_device_get_devtype (iter); - if (type && !strcmp (type, "usb_device")) - return iter; - - old = iter; - iter = g_udev_device_get_parent (old); - g_object_unref (old); - } - g_object_unref (child); - - return NULL; + if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM) + return 10; + if (capabilities & CAP_CDMA) + return 10; + return 0; } -#define PROP_GSM "ID_MM_MODEM_GSM" -#define PROP_CDMA "ID_MM_MODEM_IS707_A" -#define PROP_EVDO1 "ID_MM_MODEM_IS856" -#define PROP_EVDOA "ID_MM_MODEM_IS856_A" - -static GUdevDevice * -get_device_type (MMPlugin *plugin, - const char *subsys, - const char *name, - gboolean *gsm, - gboolean *cdma) +static void +probe_result (MMPluginBase *base, + MMPluginBaseSupportsTask *task, + guint32 capabilities, + gpointer user_data) { - MMPluginGobiPrivate *priv = MM_PLUGIN_GOBI_GET_PRIVATE (plugin); - GUdevDevice *device; - - g_return_val_if_fail (plugin != NULL, NULL); - g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL); - g_return_val_if_fail (subsys != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - device = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name); - if (!device) - return NULL; - - if (g_udev_device_get_property_as_boolean (device, PROP_GSM)) - *gsm = TRUE; - if ( g_udev_device_get_property_as_boolean (device, PROP_CDMA) - || g_udev_device_get_property_as_boolean (device, PROP_EVDO1) - || g_udev_device_get_property_as_boolean (device, PROP_EVDOA)) - *cdma = TRUE; - - return device; + mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities)); } -static guint32 -supports_port (MMPlugin *plugin, - const char *subsys, - const char *name) +static MMPluginSupportsResult +supports_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task) { - GUdevDevice *device, *physdev = NULL; - guint32 level = 0; - gboolean gsm = FALSE, cdma = FALSE; - char *driver = NULL; - - g_return_val_if_fail (plugin != NULL, 0); - g_return_val_if_fail (MM_IS_PLUGIN (plugin), 0); - g_return_val_if_fail (subsys != NULL, 0); - g_return_val_if_fail (name != NULL, 0); + GUdevDevice *port; + guint32 cached = 0, level; + const char *driver; /* Can't do anything with non-serial ports */ - if (strcmp (subsys, "tty")) - return 0; - - device = get_device_type (plugin, subsys, name, &gsm, &cdma); - if (!device) - return 0; + 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 (!gsm && !cdma) - goto out; - - driver = get_driver_name (device); + driver = mm_plugin_base_supports_task_get_driver (task); if (!driver || strcmp (driver, "qcserial")) - goto out; + 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; + } - physdev = find_physical_device (device); - if (!physdev) - goto out; - g_object_unref (physdev); - level = 10; + /* Otherwise kick off a probe */ + if (mm_plugin_base_probe_port (base, task, NULL)) + return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS; -out: - g_object_unref (device); - return level; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; } static MMModem * -grab_port (MMPlugin *plugin, - const char *subsys, - const char *name, +grab_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task, GError **error) { - MMPluginGobi *self = MM_PLUGIN_GOBI (plugin); - GUdevDevice *device = NULL, *physdev = NULL; - const char *devfile, *sysfs_path; - char *driver = NULL; + GUdevDevice *port = NULL, *physdev = NULL; MMModem *modem = NULL; - gboolean gsm = FALSE, cdma = FALSE; - - g_return_val_if_fail (subsys != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); + const char *name, *subsys, *sysfs_path; + guint32 caps; - /* Can't do anything with non-serial ports */ - if (strcmp (subsys, "tty")) - return NULL; - - device = get_device_type (plugin, subsys, name, &gsm, &cdma); - if (!device) { - g_set_error (error, 0, 0, "Could not get port's udev device."); - return NULL; - } - - if (!gsm && !cdma) { - g_set_error (error, 0, 0, "Modem unsupported (not GSM or CDMA)."); - goto out; - } - - physdev = find_physical_device (device); - if (!physdev) { - g_set_error (error, 0, 0, "Could not get ports's physical device."); - goto out; - } - - devfile = g_udev_device_get_device_file (device); - if (!devfile) { - g_set_error (error, 0, 0, "Could not get port's sysfs file."); - goto out; - } - - driver = get_driver_name (device); - if (!driver) { - g_set_error (error, 0, 0, "Could not get port's driver name."); - goto out; - } + 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."); - goto out; + return NULL; } - modem = mm_plugin_base_find_modem (MM_PLUGIN_BASE (self), sysfs_path); - if (!modem) { - if (gsm) { + 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, - driver, - mm_plugin_get_name (plugin)); - } else if (cdma) { + 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, - driver, - mm_plugin_get_name (plugin)); + 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, error)) { + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) { g_object_unref (modem); - modem = NULL; + return NULL; } } - - if (modem) - mm_plugin_base_add_modem (MM_PLUGIN_BASE (self), modem); } else { - if (gsm || cdma) { - if (!mm_modem_grab_port (modem, subsys, name, error)) - modem = NULL; + if (caps & (MM_PLUGIN_BASE_PORT_CAP_GSM | CAP_CDMA)) { + modem = existing; + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) + return NULL; } } -out: - g_free (driver); - g_object_unref (device); - g_object_unref (physdev); return modem; } -static const char * -get_name (MMPlugin *plugin) -{ - return "Gobi"; -} - /*****************************************************************************/ static void -plugin_init (MMPlugin *plugin_class) -{ - /* interface implementation */ - plugin_class->get_name = get_name; - plugin_class->supports_port = supports_port; - plugin_class->grab_port = grab_port; -} - -static void mm_plugin_gobi_init (MMPluginGobi *self) { - MMPluginGobiPrivate *priv = MM_PLUGIN_GOBI_GET_PRIVATE (self); - const char *subsys[2] = { "tty", NULL }; - - priv->client = g_udev_client_new (subsys); -} - -static void -dispose (GObject *object) -{ - MMPluginGobiPrivate *priv = MM_PLUGIN_GOBI_GET_PRIVATE (object); - - g_object_unref (priv->client); + g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL); } static void mm_plugin_gobi_class_init (MMPluginGobiClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass); - g_type_class_add_private (object_class, sizeof (MMPluginGobiPrivate)); - - object_class->dispose = dispose; + pb_class->supports_port = supports_port; + pb_class->grab_port = grab_port; } + diff --git a/plugins/mm-plugin-hso.c b/plugins/mm-plugin-hso.c index 9481bbf4..edcabab2 100644 --- a/plugins/mm-plugin-hso.c +++ b/plugins/mm-plugin-hso.c @@ -23,165 +23,89 @@ #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, MM_TYPE_PLUGIN_BASE, - 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; -#define MM_PLUGIN_HSO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_HSO, MMPluginHsoPrivate)) - -typedef struct { - GUdevClient *client; -} MMPluginHsoPrivate; - 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 char * -get_driver_name (GUdevDevice *device) +static guint32 +get_level_for_capabilities (guint32 capabilities) { - GUdevDevice *parent = NULL; - const char *driver; - char *ret; - - driver = g_udev_device_get_driver (device); - if (!driver) { - parent = g_udev_device_get_parent (device); - if (parent) - driver = g_udev_device_get_driver (parent); - } - - if (driver) - ret = g_strdup (driver); - if (parent) - g_object_unref (parent); - - return ret; + if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM) + return 10; + return 0; } -static GUdevDevice * -find_physical_device (GUdevDevice *child) +static void +probe_result (MMPluginBase *base, + MMPluginBaseSupportsTask *task, + guint32 capabilities, + gpointer user_data) { - GUdevDevice *iter, *old = NULL; - const char *type; - - g_return_val_if_fail (child != NULL, NULL); - - /* Walk the parents to find the first 'usb_device' for this device. */ - iter = g_object_ref (child); - while (iter) { - type = g_udev_device_get_devtype (iter); - if (type && !strcmp (type, "usb_device")) - return iter; - - old = iter; - iter = g_udev_device_get_parent (old); - g_object_unref (old); - } - g_object_unref (child); - - return NULL; + mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities)); } -static GUdevDevice * -get_device (GUdevClient *client, - const char *subsys, - const char *name, - GUdevDevice **physdev, - char **driver, - GError **error) +static MMPluginSupportsResult +supports_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task) { - GUdevDevice *device = NULL; + GUdevDevice *port; + guint32 cached = 0, level; + const char *driver; - if (strcmp (subsys, "tty") && strcmp (subsys, "net")) { - g_set_error (error, 0, 0, "Unsupported subsystem."); - return NULL; - } + port = mm_plugin_base_supports_task_get_port (task); - device = g_udev_client_query_by_subsystem_and_name (client, subsys, name); - if (!device) { - g_set_error (error, 0, 0, "Coud not get port's udev device."); - return NULL; - } + driver = mm_plugin_base_supports_task_get_driver (task); + if (!driver || strcmp (driver, "hso")) + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; - *driver = get_driver_name (device); - if (!*driver || strcmp (*driver, "hso")) { - g_set_error (error, 0, 0, "Unsupported driver (not 'hso')."); - g_object_unref (device); - device = NULL; - goto out; + 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; } - *physdev = find_physical_device (device); - if (!*physdev) { - g_set_error (error, 0, 0, "Could not get port's physical udev device."); - g_object_unref (device); - device = NULL; - } + /* Otherwise kick off a probe */ + if (mm_plugin_base_probe_port (base, task, NULL)) + return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS; -out: - return device; -} - -static guint32 -supports_port (MMPlugin *plugin, - const char *subsys, - const char *name) -{ - MMPluginHsoPrivate *priv = MM_PLUGIN_HSO_GET_PRIVATE (plugin); - GUdevDevice *device, *physdev = NULL; - guint32 level = 0; - char *driver = NULL; - - g_return_val_if_fail (plugin != NULL, 0); - g_return_val_if_fail (MM_IS_PLUGIN (plugin), 0); - g_return_val_if_fail (subsys != NULL, 0); - g_return_val_if_fail (name != NULL, 0); - - device = get_device (priv->client, subsys, name, &physdev, &driver, NULL); - if (device) - level = 10; - - g_free (driver); - if (physdev) - g_object_unref (physdev); - if (device) - g_object_unref (device); - return level; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; } static MMModem * -grab_port (MMPlugin *plugin, - const char *subsys, - const char *name, +grab_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task, GError **error) { - MMPluginHso *self = MM_PLUGIN_HSO (plugin); - MMPluginHsoPrivate *priv = MM_PLUGIN_HSO_GET_PRIVATE (plugin); - GUdevDevice *device = NULL, *physdev = NULL; - const char *sysfs_path = NULL; - char *driver = NULL, *devfile = NULL; + GUdevDevice *port = NULL, *physdev = NULL; MMModem *modem = NULL; + const char *name, *subsys, *sysfs_path; + char *devfile; + guint32 caps; - g_return_val_if_fail (subsys != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); + port = mm_plugin_base_supports_task_get_port (task); + g_assert (port); - device = get_device (priv->client, subsys, name, &physdev, &driver, error); - if (!device) { - g_set_error (error, 0, 0, "Could not get port's udev device."); - return NULL; - } + subsys = g_udev_device_get_subsystem (port); + name = g_udev_device_get_name (port); - devfile = g_strdup (g_udev_device_get_device_file (device)); + 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, @@ -200,80 +124,54 @@ grab_port (MMPlugin *plugin, } } + 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; } - modem = mm_plugin_base_find_modem (MM_PLUGIN_BASE (self), sysfs_path); - if (!modem) { - modem = mm_modem_hso_new (sysfs_path, - driver, - mm_plugin_get_name (plugin)); + caps = mm_plugin_base_supports_task_get_probed_capabilities (task); + if (!existing) { + if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) { + 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, error)) { + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) { g_object_unref (modem); - modem = NULL; + return NULL; } } - - if (modem) - mm_plugin_base_add_modem (MM_PLUGIN_BASE (self), modem); } else { - if (!mm_modem_grab_port (modem, subsys, name, error)) - modem = NULL; + if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) { + modem = existing; + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) + return NULL; + } } out: g_free (devfile); - g_free (driver); - g_object_unref (device); - g_object_unref (physdev); return modem; } -static const char * -get_name (MMPlugin *plugin) -{ - return "HSO"; -} - /*****************************************************************************/ static void -plugin_init (MMPlugin *plugin_class) -{ - /* interface implementation */ - plugin_class->get_name = get_name; - plugin_class->supports_port = supports_port; - plugin_class->grab_port = grab_port; -} - -static void mm_plugin_hso_init (MMPluginHso *self) { - MMPluginHsoPrivate *priv = MM_PLUGIN_HSO_GET_PRIVATE (self); - const char *subsys[] = { "tty", "net", NULL }; - - priv->client = g_udev_client_new (subsys); -} - -static void -dispose (GObject *object) -{ - MMPluginHsoPrivate *priv = MM_PLUGIN_HSO_GET_PRIVATE (object); - - g_object_unref (priv->client); + g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL); } static void mm_plugin_hso_class_init (MMPluginHsoClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMPluginHsoPrivate)); + MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass); - object_class->dispose = dispose; + pb_class->supports_port = supports_port; + pb_class->grab_port = grab_port; } diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c index 3ea70865..4ef8c578 100644 --- a/plugins/mm-plugin-huawei.c +++ b/plugins/mm-plugin-huawei.c @@ -22,269 +22,316 @@ #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, MM_TYPE_PLUGIN_BASE, - 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; -#define MM_PLUGIN_HUAWEI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiPrivate)) - -typedef struct { - GUdevClient *client; -} MMPluginHuaweiPrivate; - - 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 char * -get_driver_name (GUdevDevice *device) -{ - GUdevDevice *parent = NULL; - const char *driver; - char *ret; - - driver = g_udev_device_get_driver (device); - if (!driver) { - parent = g_udev_device_get_parent (device); - if (parent) - driver = g_udev_device_get_driver (parent); - } +#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) - if (driver) - ret = g_strdup (driver); - if (parent) - g_object_unref (parent); - - return ret; +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 GUdevDevice * -find_physical_device (GUdevDevice *child) +static void +probe_result (MMPluginBase *base, + MMPluginBaseSupportsTask *task, + guint32 capabilities, + gpointer user_data) { - GUdevDevice *iter, *old = NULL; - const char *bus, *type; + mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities)); +} - g_return_val_if_fail (child != NULL, NULL); +#define TAG_SUPPORTS_INFO "huawei-supports-info" - bus = g_udev_device_get_property (child, "ID_BUS"); - if (!bus) - return NULL; +typedef struct { + MMSerialPort *serial; + guint id; + gboolean secondary; +} HuaweiSupportsInfo; - if (strcmp (bus, "usb")) - return NULL; +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); +} - /* Walk the parents to find the 'usb_device' for this device. */ - iter = g_object_ref (child); - while (iter) { - type = g_udev_device_get_devtype (iter); - if (type && !strcmp (type, "usb_device")) - return iter; +static gboolean +probe_secondary_supported (gpointer user_data) +{ + MMPluginBaseSupportsTask *task = user_data; + HuaweiSupportsInfo *info; - old = iter; - iter = g_udev_device_get_parent (old); - g_object_unref (old); - } - g_object_unref (child); + info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO); - return NULL; -} + info->id = 0; + g_object_unref (info->serial); + info->serial = NULL; -#define PROP_GSM "ID_MM_MODEM_GSM" + /* Yay, supported, we got an unsolicited message */ + info->secondary = TRUE; + mm_plugin_base_supports_task_complete (task, 10); + return FALSE; +} -static GUdevDevice * -get_device (GUdevClient *client, - const char *subsys, - const char *name, - GUdevDevice **physdev) +static void +probe_secondary_handle_msg (MMSerialPort *port, + GMatchInfo *match_info, + gpointer user_data) { - GUdevDevice *device; - const char *tmp; + MMPluginBaseSupportsTask *task = user_data; + HuaweiSupportsInfo *info; - /* Can't do anything with non-serial ports */ - if (strcmp (subsys, "tty")) - return NULL; + 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); +} - device = g_udev_client_query_by_subsystem_and_name (client, subsys, name); - if (!device) - return NULL; +static gboolean +probe_secondary_timeout (gpointer user_data) +{ + MMPluginBaseSupportsTask *task = user_data; + HuaweiSupportsInfo *info; - tmp = g_udev_device_get_property (device, "ID_BUS"); - if (!tmp || strcmp (tmp, "usb")) - goto error; + info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO); + info->id = 0; + g_object_unref (info->serial); + info->serial = NULL; - if (!g_udev_device_get_property_as_boolean (device, PROP_GSM)) - goto error; + /* Not supported by this plugin */ + mm_plugin_base_supports_task_complete (task, 0); + return FALSE; +} - *physdev = find_physical_device (device); - if (*physdev) - return device; +static void +add_regex (MMSerialPort *port, const char *match, gpointer user_data) +{ + GRegex *regex; -error: - g_object_unref (device); - return NULL; + 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 guint32 -supports_port (MMPlugin *plugin, - const char *subsys, - const char *name) +static MMPluginSupportsResult +supports_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task) { - MMPluginHuaweiPrivate *priv = MM_PLUGIN_HUAWEI_GET_PRIVATE (plugin); - GUdevDevice *device, *physdev = NULL; - guint32 level = 0; + GUdevDevice *port; + guint32 cached = 0, level; + const char *subsys, *name; + int usbif; guint16 vendor = 0, product = 0; + guint32 existing_type = MM_MODEM_TYPE_UNKNOWN; - device = get_device (priv->client, subsys, name, &physdev); - if (!device) - goto out; - g_object_unref (physdev); + /* 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_device_ids (MM_PLUGIN_BASE (plugin), subsys, name, &vendor, &product)) - goto out; + 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) - goto out; + 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; + } + + /* 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; + } - if (product == 0x1001 || product == 0x1003 || product == 0x1004) - level = 10; + return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS; + } -out: - if (device) - g_object_unref (device); - return level; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; } static MMModem * -grab_port (MMPlugin *plugin, - const char *subsys, - const char *name, +grab_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task, GError **error) { - MMPluginHuawei *self = MM_PLUGIN_HUAWEI (plugin); - MMPluginHuaweiPrivate *priv = MM_PLUGIN_HUAWEI_GET_PRIVATE (plugin); - GUdevDevice *device = NULL, *physdev = NULL; - const char *devfile, *sysfs_path; - char *driver = NULL; + GUdevDevice *port = NULL, *physdev = NULL; MMModem *modem = NULL; + const char *name, *subsys, *devfile, *sysfs_path; + guint32 caps; guint16 product = 0; - g_return_val_if_fail (subsys != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - device = get_device (priv->client, subsys, name, &physdev); - if (!device) - goto out; + port = mm_plugin_base_supports_task_get_port (task); + g_assert (port); - devfile = g_udev_device_get_device_file (device); + devfile = g_udev_device_get_device_file (port); if (!devfile) { g_set_error (error, 0, 0, "Could not get port's sysfs file."); - goto out; - } - - driver = get_driver_name (device); - if (!driver) { - g_set_error (error, 0, 0, "Could not get port's driver name."); - goto out; + 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."); - goto out; + return NULL; } - if (!mm_plugin_base_get_device_ids (MM_PLUGIN_BASE (plugin), subsys, name, NULL, &product)) { + subsys = g_udev_device_get_subsystem (port); + name = g_udev_device_get_name (port); + + if (!mm_plugin_base_get_device_ids (base, subsys, name, NULL, &product)) { g_set_error (error, 0, 0, "Could not get modem product ID."); - goto out; + return NULL; } - modem = mm_plugin_base_find_modem (MM_PLUGIN_BASE (self), sysfs_path); - if (!modem) { - if (product == 0x1001) { - /* This modem is handled by generic GSM driver */ - modem = mm_generic_gsm_new (sysfs_path, - driver, - mm_plugin_get_name (plugin)); - } else { - modem = mm_modem_huawei_new (sysfs_path, - driver, - mm_plugin_get_name (plugin)); + 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 (modem) { - if (!mm_modem_grab_port (modem, subsys, name, error)) { -g_message ("%s: couldn't grab port", __func__); + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) { g_object_unref (modem); - modem = NULL; - goto out; + return NULL; } - mm_plugin_base_add_modem (MM_PLUGIN_BASE (self), modem); } } else { - if (!mm_modem_grab_port (modem, subsys, name, error)) - modem = NULL; + HuaweiSupportsInfo *info; + gboolean huawei_is_secondary = FALSE; + + 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; } -out: - g_free (driver); - g_object_unref (device); - g_object_unref (physdev); -g_message ("%s: port %s / %s modem %p", __func__, subsys, name, modem); return modem; } -static const char * -get_name (MMPlugin *plugin) -{ - return "Huawei"; -} - - /*****************************************************************************/ static void -plugin_init (MMPlugin *plugin_class) -{ - /* interface implementation */ - plugin_class->get_name = get_name; - plugin_class->supports_port = supports_port; - plugin_class->grab_port = grab_port; -} - -static void mm_plugin_huawei_init (MMPluginHuawei *self) { - MMPluginHuaweiPrivate *priv = MM_PLUGIN_HUAWEI_GET_PRIVATE (self); - const char *subsys[2] = { "tty", NULL }; - - priv->client = g_udev_client_new (subsys); -} - -static void -dispose (GObject *object) -{ - MMPluginHuaweiPrivate *priv = MM_PLUGIN_HUAWEI_GET_PRIVATE (object); - - g_object_unref (priv->client); + g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL); } static void mm_plugin_huawei_class_init (MMPluginHuaweiClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMPluginHuaweiPrivate)); + MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass); - object_class->dispose = dispose; + pb_class->supports_port = supports_port; + pb_class->grab_port = grab_port; } diff --git a/plugins/mm-plugin-moto-c.c b/plugins/mm-plugin-moto-c.c index 693dd61d..a77e65a8 100644 --- a/plugins/mm-plugin-moto-c.c +++ b/plugins/mm-plugin-moto-c.c @@ -22,255 +22,144 @@ #include "mm-plugin-moto-c.h" #include "mm-modem-moto-c-gsm.h" -static void plugin_init (MMPlugin *plugin_class); - -G_DEFINE_TYPE_EXTENDED (MMPluginMotoC, mm_plugin_moto_c, MM_TYPE_PLUGIN_BASE, - 0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init)) +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; -#define MM_PLUGIN_MOTO_C_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_MOTO_C, MMPluginMotoCPrivate)) - -typedef struct { - GUdevClient *client; -} MMPluginMotoCPrivate; - - G_MODULE_EXPORT MMPlugin * mm_plugin_create (void) { - return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_MOTO_C, NULL)); + return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_MOTO_C, + MM_PLUGIN_BASE_NAME, "MotoC", + NULL)); } /*****************************************************************************/ -static char * -get_driver_name (GUdevDevice *device) -{ - GUdevDevice *parent = NULL; - const char *driver; - char *ret; - - driver = g_udev_device_get_driver (device); - if (!driver) { - parent = g_udev_device_get_parent (device); - if (parent) - driver = g_udev_device_get_driver (parent); - } - - if (driver) - ret = g_strdup (driver); - if (parent) - g_object_unref (parent); - - return ret; -} - -static GUdevDevice * -find_physical_device (GUdevDevice *child) +static void +probe_result (MMPluginBase *base, + MMPluginBaseSupportsTask *task, + guint32 capabilities, + gpointer user_data) { - GUdevDevice *iter, *old = NULL; - const char *bus, *type; - - g_return_val_if_fail (child != NULL, NULL); - - bus = g_udev_device_get_property (child, "ID_BUS"); - if (!bus) - return NULL; - - if (strcmp (bus, "usb")) - return NULL; - - /* Walk the parents to find the 'usb_device' for this device. */ - iter = g_object_ref (child); - while (iter) { - type = g_udev_device_get_devtype (iter); - if (type && !strcmp (type, "usb_device")) - return iter; + guint32 level = 0; - old = iter; - iter = g_udev_device_get_parent (old); - g_object_unref (old); - } - g_object_unref (child); + if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM) + level = 10; - return NULL; + mm_plugin_base_supports_task_complete (task, level); } -#define PROP_GSM "ID_MM_MODEM_GSM" - -static guint32 -supports_port (MMPlugin *plugin, - const char *subsys, - const char *name) +static MMPluginSupportsResult +supports_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task) { - MMPluginMotoCPrivate *priv = MM_PLUGIN_MOTO_C_GET_PRIVATE (plugin); - GUdevDevice *device, *physdev = NULL; - guint32 level = 0; + GUdevDevice *port; const char *tmp; - - g_return_val_if_fail (plugin != NULL, 0); - g_return_val_if_fail (MM_IS_PLUGIN (plugin), 0); - g_return_val_if_fail (subsys != NULL, 0); - g_return_val_if_fail (name != NULL, 0); + guint32 cached = 0; /* Can't do anything with non-serial ports */ - if (strcmp (subsys, "tty")) - return 0; - - device = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name); - if (!device) - return 0; + 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 (device, "ID_BUS"); + tmp = g_udev_device_get_property (port, "ID_BUS"); if (!tmp || strcmp (tmp, "usb")) - goto out; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; - tmp = g_udev_device_get_property (device, "ID_VENDOR_ID"); + tmp = g_udev_device_get_property (port, "ID_VENDOR_ID"); if (!tmp || strcmp (tmp, "22b8")) - goto out; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; - tmp = g_udev_device_get_property (device, "ID_MODEL_ID"); + tmp = g_udev_device_get_property (port, "ID_MODEL_ID"); if (!tmp || strcmp (tmp, "3802")) - goto out; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; - if (!g_udev_device_get_property_as_boolean (device, PROP_GSM)) - goto out; + 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; + } - physdev = find_physical_device (device); - if (!physdev) - goto out; - g_object_unref (physdev); - level = 10; + /* Otherwise kick off a probe */ + if (mm_plugin_base_probe_port (base, task, NULL)) + return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS; -out: - g_object_unref (device); - return level; + return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; } static MMModem * -grab_port (MMPlugin *plugin, - const char *subsys, - const char *name, +grab_port (MMPluginBase *base, + MMModem *existing, + MMPluginBaseSupportsTask *task, GError **error) { - MMPluginMotoC *self = MM_PLUGIN_MOTO_C (plugin); - MMPluginMotoCPrivate *priv = MM_PLUGIN_MOTO_C_GET_PRIVATE (plugin); - GUdevDevice *device = NULL, *physdev = NULL; - const char *devfile, *sysfs_path; - char *driver = NULL; + GUdevDevice *port = NULL, *physdev = NULL; MMModem *modem = NULL; + const char *name, *subsys, *devfile, *sysfs_path; - g_return_val_if_fail (subsys != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - /* Can't do anything with non-serial ports */ - if (strcmp (subsys, "tty")) - return NULL; - - device = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name); - if (!device) { - g_set_error (error, 0, 0, "Could not get port's udev device."); - return NULL; - } - - if (!g_udev_device_get_property_as_boolean (device, PROP_GSM)) { - g_set_error (error, 0, 0, "Modem unsupported (not GSM)."); - goto out; - } - - physdev = find_physical_device (device); - if (!physdev) { - g_set_error (error, 0, 0, "Could not get ports's physical device."); - goto out; - } - - devfile = g_udev_device_get_device_file (device); + devfile = g_udev_device_get_device_file (port); if (!devfile) { g_set_error (error, 0, 0, "Could not get port's sysfs file."); - goto out; - } - - driver = get_driver_name (device); - if (!driver) { - g_set_error (error, 0, 0, "Could not get port's driver name."); - goto out; + 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."); - goto out; + return NULL; } - modem = mm_plugin_base_find_modem (MM_PLUGIN_BASE (self), sysfs_path); - if (!modem) { + 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, - driver, - mm_plugin_get_name (plugin)); + 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, error)) { + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) { g_object_unref (modem); - modem = NULL; + return NULL; } } - - if (modem) - mm_plugin_base_add_modem (MM_PLUGIN_BASE (self), modem); } else { - if (!mm_modem_grab_port (modem, subsys, name, error)) - modem = NULL; + modem = existing; + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) + return NULL; } -out: - g_free (driver); - g_object_unref (device); - g_object_unref (physdev); return modem; } -static const char * -get_name (MMPlugin *plugin) -{ - return "MotoC"; -} - /*****************************************************************************/ static void -plugin_init (MMPlugin *plugin_class) -{ - /* interface implementation */ - plugin_class->get_name = get_name; - plugin_class->supports_port = supports_port; - plugin_class->grab_port = grab_port; -} - -static void mm_plugin_moto_c_init (MMPluginMotoC *self) { - MMPluginMotoCPrivate *priv = MM_PLUGIN_MOTO_C_GET_PRIVATE (self); - const char *subsys[2] = { "tty", NULL }; - - priv->client = g_udev_client_new (subsys); + g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL); } static void dispose (GObject *object) { - MMPluginMotoCPrivate *priv = MM_PLUGIN_MOTO_C_GET_PRIVATE (object); - - g_object_unref (priv->client); } static void mm_plugin_moto_c_class_init (MMPluginMotoCClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMPluginMotoCPrivate)); + MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass); object_class->dispose = dispose; + + pb_class->supports_port = supports_port; + pb_class->grab_port = grab_port; } 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..9a02a059 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,157 @@ 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; + 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); + + caps = mm_plugin_base_supports_task_get_probed_capabilities (task); + if (!existing) { + if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) { + 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))); + } - modem = MM_MODEM (mm_modem_sierra_new (data_device, driver)); + if (modem) { + if (!mm_modem_grab_port (modem, subsys, name, NULL, error)) { + g_object_unref (modem); + return NULL; + } + } + } else { + gpointer gsm_data = NULL; - libhal_free_string (data_device); - libhal_free_string (driver); + /* Is this a GSM secondary port? */ + if (g_object_get_data (G_OBJECT (task), TAG_SIERRA_SECONDARY_PORT)) + gsm_data = GUINT_TO_POINTER (TRUE); + + 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 +186,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); |