Merge remote-tracking branch 'cros/upstream' into 'cros/master'. Change-Id: I22368813ff52c203507d5a72cbed75d3769e2be5
diff --git a/libmm-common/mm-bearer-properties.c b/libmm-common/mm-bearer-properties.c index 6475ba7..8eb665c 100644 --- a/libmm-common/mm-bearer-properties.c +++ b/libmm-common/mm-bearer-properties.c
@@ -440,6 +440,22 @@ /*****************************************************************************/ +gboolean +mm_bearer_properties_cmp (MMBearerProperties *a, + MMBearerProperties *b) +{ + return ((!g_strcmp0 (a->priv->apn, b->priv->apn)) && + (!g_strcmp0 (a->priv->ip_type, b->priv->ip_type)) && + (!g_strcmp0 (a->priv->number, b->priv->number)) && + (!g_strcmp0 (a->priv->user, b->priv->user)) && + (!g_strcmp0 (a->priv->password, b->priv->password)) && + (a->priv->allow_roaming == b->priv->allow_roaming) && + (a->priv->allow_roaming_set == b->priv->allow_roaming_set) && + (a->priv->rm_protocol == b->priv->rm_protocol)); +} + +/*****************************************************************************/ + MMBearerProperties * mm_bearer_properties_new (void) { @@ -457,6 +473,13 @@ /* Some defaults */ self->priv->allow_roaming = TRUE; self->priv->rm_protocol = MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN; + + /* At some point in the future, this default should probably be changed + * to IPV4V6. However, presently support for this PDP type is rare. An + * even better approach would likely be to query which PDP types the + * modem supports (using AT+CGDCONT=?), and set the default accordingly + */ + self->priv->ip_type = g_strdup ("IP"); } static void
diff --git a/libmm-common/mm-bearer-properties.h b/libmm-common/mm-bearer-properties.h index 407eb0e..3288c33 100644 --- a/libmm-common/mm-bearer-properties.h +++ b/libmm-common/mm-bearer-properties.h
@@ -86,6 +86,9 @@ GVariant *mm_bearer_properties_get_dictionary (MMBearerProperties *self); +gboolean mm_bearer_properties_cmp (MMBearerProperties *a, + MMBearerProperties *b); + G_END_DECLS #endif /* MM_BEARER_PROPERTIES_H */
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index da960a8..af642b4 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am
@@ -49,7 +49,8 @@ libmm-plugin-hso.la \ libmm-plugin-anydata.la \ libmm-plugin-linktop.la \ - libmm-plugin-simtech.la + libmm-plugin-simtech.la \ + libmm-plugin-wavecom.la #pkglib_LTLIBRARIES = \ # libmm-plugin-generic.la \ @@ -150,15 +151,15 @@ #libmm_plugin_sierra_la_LIBADD = \ # $(builddir)/libicera-utils.la -## Wavecom (Sierra Airlink) -#libmm_plugin_wavecom_la_SOURCES = \ -# mm-plugin-wavecom.c \ -# mm-plugin-wavecom.h \ -# mm-modem-wavecom-gsm.c \ -# mm-modem-wavecom-gsm.h -#libmm_plugin_wavecom_la_CPPFLAGS = $(PLUGIN_COMMON_COMPILER_FLAGS) -#libmm_plugin_wavecom_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS) -# +# Wavecom (Sierra Airlink) +libmm_plugin_wavecom_la_SOURCES = \ + wavecom/mm-plugin-wavecom.c \ + wavecom/mm-plugin-wavecom.h \ + wavecom/mm-broadband-modem-wavecom.c \ + wavecom/mm-broadband-modem-wavecom.h +libmm_plugin_wavecom_la_CPPFLAGS = $(PLUGIN_COMMON_COMPILER_FLAGS) +libmm_plugin_wavecom_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS) + ## Novatel #libmm_plugin_novatel_la_SOURCES = \ # mm-plugin-novatel.c \
diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c index a3d35e8..d4d1bcf 100644 --- a/plugins/cinterion/mm-broadband-modem-cinterion.c +++ b/plugins/cinterion/mm-broadband-modem-cinterion.c
@@ -749,7 +749,7 @@ if (G_UNLIKELY (!bands_array)) bands_array = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); - for (j = 0; j < 4 && bands_2g[i].mm_bands[j] != 0; j++) + for (j = 0; j < bands_2g[i].n_mm_bands; j++) g_array_append_val (bands_array, bands_2g[i].mm_bands[j]); break;
diff --git a/plugins/gobi/mm-broadband-modem-gobi.c b/plugins/gobi/mm-broadband-modem-gobi.c index 01568b4..6c71262 100644 --- a/plugins/gobi/mm-broadband-modem-gobi.c +++ b/plugins/gobi/mm-broadband-modem-gobi.c
@@ -59,7 +59,7 @@ p = strchr (p, ','); if (p) { /* We are reporting ALL 3GPP access technologies here */ - *access_technologies = mm_3gpp_string_to_access_tech (p + 1); + *access_technologies = mm_string_to_access_tech (p + 1); *mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; return TRUE; }
diff --git a/plugins/iridium/mm-bearer-iridium.c b/plugins/iridium/mm-bearer-iridium.c index 1caa68e..93936c2 100644 --- a/plugins/iridium/mm-bearer-iridium.c +++ b/plugins/iridium/mm-bearer-iridium.c
@@ -385,21 +385,9 @@ /*****************************************************************************/ -static gboolean -cmp_properties (MMBearer *self, - MMBearerProperties *properties) -{ - return (mm_bearer_properties_get_apn (properties) == NULL && - mm_bearer_properties_get_ip_type (properties) == NULL && - mm_bearer_properties_get_number (properties) == NULL && - mm_bearer_properties_get_rm_protocol (properties) == MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN && - mm_bearer_properties_get_allow_roaming (properties)); -} - -/*****************************************************************************/ - MMBearer * -mm_bearer_iridium_new (MMBroadbandModemIridium *modem) +mm_bearer_iridium_new (MMBroadbandModemIridium *modem, + MMBearerProperties *config) { MMBearer *bearer; @@ -408,6 +396,7 @@ * g_object_get() here */ bearer = g_object_new (MM_TYPE_BEARER_IRIDIUM, MM_BEARER_MODEM, modem, + MM_BEARER_CONFIG, config, "ip-timeout", MM_BEARER_IRIDIUM_IP_TIMEOUT_DEFAULT, NULL); @@ -428,7 +417,6 @@ MMBearerClass *bearer_class = MM_BEARER_CLASS (klass); /* Virtual methods */ - bearer_class->cmp_properties = cmp_properties; bearer_class->connect = connect; bearer_class->connect_finish = connect_finish; bearer_class->disconnect = disconnect;
diff --git a/plugins/iridium/mm-bearer-iridium.h b/plugins/iridium/mm-bearer-iridium.h index ccb3307..191de0f 100644 --- a/plugins/iridium/mm-bearer-iridium.h +++ b/plugins/iridium/mm-bearer-iridium.h
@@ -48,6 +48,7 @@ /* Iridium bearer creation implementation. * NOTE it is *not* a broadband bearer, so not async-initable */ -MMBearer *mm_bearer_iridium_new (MMBroadbandModemIridium *modem); +MMBearer *mm_bearer_iridium_new (MMBroadbandModemIridium *modem, + MMBearerProperties *config); #endif /* MM_BEARER_IRIDIUM_H */
diff --git a/plugins/iridium/mm-broadband-modem-iridium.c b/plugins/iridium/mm-broadband-modem-iridium.c index 4ea8f06..1235ed2 100644 --- a/plugins/iridium/mm-broadband-modem-iridium.c +++ b/plugins/iridium/mm-broadband-modem-iridium.c
@@ -360,10 +360,9 @@ callback, user_data, create_bearer); - /* We just create a MMBearerIridium - * Note that we do not need to use properties here */ mm_dbg ("Creating Iridium bearer..."); - bearer = mm_bearer_iridium_new (MM_BROADBAND_MODEM_IRIDIUM (self)); + bearer = mm_bearer_iridium_new (MM_BROADBAND_MODEM_IRIDIUM (self), + properties); g_simple_async_result_set_op_res_gpointer (result, bearer, (GDestroyNotify)g_object_unref);
diff --git a/plugins/mm-modem-wavecom-gsm.c b/plugins/mm-modem-wavecom-gsm.c deleted file mode 100644 index 8b65426..0000000 --- a/plugins/mm-modem-wavecom-gsm.c +++ /dev/null
@@ -1,1174 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <config.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include "mm-errors.h" -#include "mm-modem-helpers.h" -#include "mm-modem-wavecom-gsm.h" -#include "mm-serial-parsers.h" -#include "mm-log.h" - -static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class); - -G_DEFINE_TYPE_EXTENDED (MMModemWavecomGsm, mm_modem_wavecom_gsm, MM_TYPE_GENERIC_GSM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init)) - -/* Bit flags for mobile station classes supported by the modem */ -typedef enum { - WAVECOM_MS_CLASS_UNKNOWN = 0, - /* Class C in circuit switched only mode, CS */ - WAVECOM_MS_CLASS_CC = 1 << 0, - /* Class C in GPRS only mode, PS */ - WAVECOM_MS_CLASS_CG = 1 << 1, - /* Class B (either CS or PS, not both at the same time) - * This should be the default for GSM/GPRS modems */ - WAVECOM_MS_CLASS_B = 1 << 2, - /* Class A in 3G only mode */ - WAVECOM_MS_CLASS_A = 1 << 3 -} WavecomMSClass; - -#define WAVECOM_MS_CLASS_CC_IDSTR "\"CC\"" -#define WAVECOM_MS_CLASS_CG_IDSTR "\"CG\"" -#define WAVECOM_MS_CLASS_B_IDSTR "\"B\"" -#define WAVECOM_MS_CLASS_A_IDSTR "\"A\"" - -/* Mask of all supported 2G bands */ -#define ALL_2G_BANDS \ - (MM_MODEM_GSM_BAND_EGSM | \ - MM_MODEM_GSM_BAND_DCS | \ - MM_MODEM_GSM_BAND_PCS | \ - MM_MODEM_GSM_BAND_G850) - -/* Mask of all supported 3G bands */ -#define ALL_3G_BANDS \ - (MM_MODEM_GSM_BAND_U2100 | \ - MM_MODEM_GSM_BAND_U1800 | \ - MM_MODEM_GSM_BAND_U17IV | \ - MM_MODEM_GSM_BAND_U800 | \ - MM_MODEM_GSM_BAND_U850 | \ - MM_MODEM_GSM_BAND_U900 | \ - MM_MODEM_GSM_BAND_U17IX | \ - MM_MODEM_GSM_BAND_U1900 | \ - MM_MODEM_GSM_BAND_U2600) - -#define MM_MODEM_WAVECOM_GSM_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_WAVECOM_GSM, MMModemWavecomGsmPrivate)) - -typedef struct { - /* Bitmask for supported MS classes */ - guint8 supported_ms_classes; - /* Current MS class */ - WavecomMSClass current_ms_class; - /* Current allowed mode, only for 3G devices */ - MMModemGsmAllowedMode allowed_mode; - /* Bitmask for currently active bands */ - guint32 current_bands; -} MMModemWavecomGsmPrivate; - -/* Setup relationship between 2G bands in the modem (identified by a - * single digit in ASCII) and the bitmask in ModemManager. */ -typedef struct { - gchar wavecom_band; - guint32 mm_band_mask; -} WavecomBand2G; -static const WavecomBand2G bands_2g[] = { - { '0', MM_MODEM_GSM_BAND_G850 }, - { '1', MM_MODEM_GSM_BAND_EGSM }, - { '2', MM_MODEM_GSM_BAND_DCS }, - { '3', MM_MODEM_GSM_BAND_PCS }, - { '4', (MM_MODEM_GSM_BAND_G850 | MM_MODEM_GSM_BAND_PCS) }, - { '5', (MM_MODEM_GSM_BAND_EGSM | MM_MODEM_GSM_BAND_DCS) }, - { '6', (MM_MODEM_GSM_BAND_EGSM | MM_MODEM_GSM_BAND_PCS) }, - { '7', ALL_2G_BANDS } -}; - -/* Setup relationship between the 3G band bitmask in the modem and the bitmask - * in ModemManager. */ -typedef struct { - guint32 wavecom_band_flag; - guint32 mm_band_flag; -} WavecomBand3G; -static const WavecomBand3G bands_3g[] = { - { (1 << 0), MM_MODEM_GSM_BAND_U2100 }, - { (1 << 1), MM_MODEM_GSM_BAND_U1900 }, - { (1 << 2), MM_MODEM_GSM_BAND_U1800 }, - { (1 << 3), MM_MODEM_GSM_BAND_U17IV }, - { (1 << 4), MM_MODEM_GSM_BAND_U850 }, - { (1 << 5), MM_MODEM_GSM_BAND_U800 }, - { (1 << 6), MM_MODEM_GSM_BAND_U2600 }, - { (1 << 7), MM_MODEM_GSM_BAND_U900 }, - { (1 << 8), MM_MODEM_GSM_BAND_U17IX } -}; - -MMModem * -mm_modem_wavecom_gsm_new (const char *device, - const char *driver, - const char *plugin, - guint32 vendor, - guint32 product) -{ - 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_WAVECOM_GSM, - MM_MODEM_MASTER_DEVICE, device, - MM_MODEM_DRIVER, driver, - MM_MODEM_PLUGIN, plugin, - MM_MODEM_HW_VID, vendor, - MM_MODEM_HW_PID, product, - NULL)); -} - -static const gchar * -wavecom_ms_class_to_str (WavecomMSClass class) -{ - switch (class) { - case WAVECOM_MS_CLASS_CC: - return WAVECOM_MS_CLASS_CC_IDSTR; - case WAVECOM_MS_CLASS_CG: - return WAVECOM_MS_CLASS_CG_IDSTR; - case WAVECOM_MS_CLASS_B: - return WAVECOM_MS_CLASS_B_IDSTR; - case WAVECOM_MS_CLASS_A: - return WAVECOM_MS_CLASS_A_IDSTR; - default: - g_warn_if_reached (); - return NULL; - } -} - -static void -port_grabbed (MMGenericGsm *gsm, - MMPort *port, - MMAtPortFlags pflags, - gpointer user_data) -{ - gpointer parser; - GRegex *regex; - - if (MM_IS_AT_SERIAL_PORT (port)) { - parser = mm_serial_parser_v1_new (); - - /* AT+CPIN? replies will never have an OK appended */ - regex = g_regex_new ("\\r\\n\\+CPIN: .*\\r\\n", - G_REGEX_RAW | G_REGEX_OPTIMIZE, - 0, NULL); - mm_serial_parser_v1_set_custom_regex (parser, regex, NULL); - g_regex_unref (regex); - - mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), - mm_serial_parser_v1_parse, - parser, - mm_serial_parser_v1_destroy); - } -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - /* Do nothing... see set_property() in parent, which also does nothing */ -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) { - case MM_GENERIC_GSM_PROP_POWER_UP_CMD: - /* Try to go to full functionality mode without rebooting the system. - * Works well if we previously switched off the power with CFUN=4 - */ - g_value_set_string (value, "+CFUN=1,0"); - break; - case MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD: - /* Wavecom doesn't have XOFF/XON flow control, so we enable RTS/CTS */ - g_value_set_string (value, "+IFC=2,2"); - break; - case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD: - /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and - * keeps access to the SIM */ - g_value_set_string (value, "+CFUN=4"); - break; - default: - break; - } -} - -static void -set_band_done (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) - info->error = g_error_copy (error); - else { - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - - priv->current_bands = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "new-band")); - } - - mm_callback_info_schedule (info); -} - -static void -set_2g_band (MMModemGsmNetwork *self, - MMModemGsmBand band, - MMAtSerialPort *port, - MMCallbackInfo *info) -{ - gchar wavecom_band; - gchar *cmd; - guint i; - - /* Ensure we don't get 3G bands when trying to configure 2G bands */ - if (band & ALL_3G_BANDS) { - info->error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Not allowed to set 3G bands in 2G mode"); - mm_callback_info_schedule (info); - return; - } - - /* If we get ANY, reset to all-2G bands to get the proper value */ - if (band == MM_MODEM_GSM_BAND_ANY) - band = ALL_2G_BANDS; - - /* Loop looking for allowed masks */ - wavecom_band = '\0'; - for (i = 0; i < G_N_ELEMENTS (bands_2g); i++) { - if (bands_2g[i].mm_band_mask == band) { - wavecom_band = bands_2g[i].wavecom_band; - break; - } - } - - /* If we didn't find a match, set an error */ - if (wavecom_band == '\0') { - info->error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Wrong 2G band mask: '%u'", band); - mm_callback_info_schedule (info); - return; - } - - mm_callback_info_set_data (info, - "new-band", - GUINT_TO_POINTER ((guint)band), - NULL); - - cmd = g_strdup_printf ("+WMBS=%c,1", wavecom_band); - mm_at_serial_port_queue_command (port, cmd, 3, set_band_done, info); - g_free (cmd); -} - -static void -set_3g_band (MMModemGsmNetwork *self, - MMModemGsmBand band, - MMAtSerialPort *port, - MMCallbackInfo *info) -{ - guint wavecom_band; - gchar *cmd; - guint i; - - /* Ensure we don't get 2G bands when trying to configure 2G bands */ - if (band & ALL_2G_BANDS) { - info->error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Not allowed to set 2G bands in 3G mode"); - mm_callback_info_schedule (info); - return; - } - - /* If we get ANY, reset to all-3G bands to get the proper value */ - if (band == MM_MODEM_GSM_BAND_ANY) - band = ALL_3G_BANDS; - - /* Loop looking for allowed masks */ - wavecom_band = 0; - for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) { - if (bands_3g[i].mm_band_flag & band) { - wavecom_band |= bands_3g[i].wavecom_band_flag; - } - } - - /* If we didn't find a match, set an error */ - if (wavecom_band == 0) { - info->error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Wrong 3G band mask: '%u'", band); - mm_callback_info_schedule (info); - return; - } - - mm_callback_info_set_data (info, - "new-band", - GUINT_TO_POINTER ((guint)band), - NULL); - - cmd = g_strdup_printf ("+WMBS=\"%u\",1", wavecom_band); - mm_at_serial_port_queue_command (port, cmd, 3, set_band_done, info); - g_free (cmd); -} - -static void -set_band (MMModemGsmNetwork *self, - MMModemGsmBand band, - MMModemFn callback, - gpointer user_data) -{ - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (self); - MMAtSerialPort *port; - MMCallbackInfo *info; - - info = mm_callback_info_new (MM_MODEM (self), callback, user_data); - - /* Are we trying to change the band to the same bands currently - * being used? if so, we're done */ - if (priv->current_bands == band) { - mm_callback_info_schedule (info); - return; - } - - /* Otherwise ask the modem */ - port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error); - if (!port) { - mm_callback_info_schedule (info); - return; - } - - if (priv->current_ms_class != WAVECOM_MS_CLASS_A) - set_2g_band (self, band, port, info); - else - set_3g_band (self, band, port, info); -} - -static void -get_2g_band_done (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) - info->error = g_error_copy (error); - else { - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - const gchar *p; - guint32 mm_band = MM_MODEM_GSM_BAND_UNKNOWN; - - p = mm_strip_tag (response->str, "+WMBS:"); - if (p) { - guint i; - - for (i = 0; i < G_N_ELEMENTS (bands_2g); i++) { - if (bands_2g[i].wavecom_band == *p) { - mm_band = bands_2g[i].mm_band_mask; - break; - } - } - } - - if (mm_band == MM_MODEM_GSM_BAND_UNKNOWN) { - g_set_error (&info->error, - MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Couldn't get 2G bands"); - } else { - priv->current_bands = mm_band; - mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL); - } - } - - mm_callback_info_schedule (info); -} - -static void -get_3g_band_done (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) - info->error = g_error_copy (error); - else { - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - const gchar *p; - guint mm_band = MM_MODEM_GSM_BAND_UNKNOWN; - guint32 wavecom_band; - - /* Example reply: - * AT+WUBS? --> - * <-- +WUBS: "3",1 - * <-- OK - * The "3" meaning here Band I and II are selected. - */ - - p = mm_strip_tag (response->str, "+WUBS:"); - if (*p == '"') - p++; - wavecom_band = atoi (p); - - if (wavecom_band > 0) { - guint i; - - for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) { - if (bands_3g[i].wavecom_band_flag & wavecom_band) { - mm_band |= bands_3g[i].mm_band_flag; - } - } - } - - if (mm_band == MM_MODEM_GSM_BAND_UNKNOWN) { - g_set_error (&info->error, - MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Couldn't get 3G bands"); - } else { - priv->current_bands = mm_band; - mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL); - } - } - - mm_callback_info_schedule (info); -} - -static void -get_band (MMModemGsmNetwork *self, - MMModemUIntFn callback, - gpointer user_data) -{ - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (self); - MMAtSerialPort *port; - MMCallbackInfo *info; - - info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data); - - /* If results are already cached, return them */ - if (priv->current_bands > 0) { - mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->current_bands), NULL); - mm_callback_info_schedule (info); - return; - } - - /* Otherwise ask the modem */ - port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error); - if (!port) { - mm_callback_info_schedule (info); - return; - } - - if (priv->current_ms_class != WAVECOM_MS_CLASS_A) - mm_at_serial_port_queue_command (port, "AT+WMBS?", 3, get_2g_band_done, info); - else - mm_at_serial_port_queue_command (port, "AT+WUBS?", 3, get_3g_band_done, info); -} - -static void -get_access_technology_cb (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = user_data; - MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; - const gchar *p; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) - info->error = g_error_copy (error); - else { - p = mm_strip_tag (response->str, "+WGPRSIND:"); - if (!p) { - g_set_error (&info->error, - MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Couldn't get network capabilities"); - } else { - switch (*p) { - case '1': - /* GPRS only */ - act = MM_MODEM_GSM_ACCESS_TECH_GPRS; - break; - case '2': - /* EGPRS/EDGE supported */ - act = MM_MODEM_GSM_ACCESS_TECH_EDGE; - break; - case '3': - /* 3G R99 supported */ - act = MM_MODEM_GSM_ACCESS_TECH_UMTS; - break; - case '4': - /* HSDPA supported */ - act = MM_MODEM_GSM_ACCESS_TECH_HSDPA; - break; - case '5': - /* HSUPA supported */ - act = MM_MODEM_GSM_ACCESS_TECH_HSUPA; - break; - default: - break; - } - } - } - - mm_callback_info_set_result (info, GUINT_TO_POINTER (act), NULL); - mm_callback_info_schedule (info); -} - -static void -get_access_technology (MMGenericGsm *gsm, - MMModemUIntFn callback, - gpointer user_data) -{ - MMAtSerialPort *port; - MMCallbackInfo *info; - - info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); - - port = mm_generic_gsm_get_best_at_port (gsm, &info->error); - if (!port) { - mm_callback_info_schedule (info); - return; - } - - mm_at_serial_port_queue_command (port, "+WGPRS=9,2", 3, get_access_technology_cb, info); -} - -static void -get_allowed_mode_cb (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = user_data; - MMModemWavecomGsmPrivate *priv; - gint read_mode = -1; - gchar *mode_str = NULL; - gchar *prefer_str = NULL; - GRegex *r = NULL; - GMatchInfo *match_info = NULL; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) { - info->error = g_error_copy (error); - mm_callback_info_schedule (info); - return; - } - - priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - - /* Possible responses: - * +WWSM: 0 (2G only) - * +WWSM: 1 (3G only) - * +WWSM: 2,0 (Any) - * +WWSM: 2,1 (2G preferred) - * +WWSM: 2,2 (3G preferred) - */ - r = g_regex_new ("\\r\\n\\+WWSM: ([0-2])(,([0-2]))?.*$", 0, 0, NULL); - if (r && g_regex_match_full (r, response->str, response->len, 0, 0, &match_info, NULL)) { - mode_str = g_match_info_fetch (match_info, 1); - prefer_str = g_match_info_fetch (match_info, 3); /* 3, to avoid the comma */ - - if (mode_str) { - switch (atoi (mode_str)) { - case 0: - if (!prefer_str) - read_mode = MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY; - break; - case 1: - if (!prefer_str) - read_mode = MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY; - break; - case 2: - if (prefer_str) { - switch (atoi (prefer_str)) { - case 0: - read_mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; - break; - case 1: - read_mode = MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED; - break; - case 2: - read_mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; - break; - default: - g_warn_if_reached (); - break; - } - } - break; - default: - g_warn_if_reached (); - break; - } - } - } - - if (read_mode < 0) { - info->error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Unexpected wireless data service reply: '%s' " - "(mode: '%s', prefer: '%s')", - response->str, - mode_str ? mode_str : "none", - prefer_str ? prefer_str : "none"); - } else { - priv->allowed_mode = (guint)read_mode; - mm_callback_info_set_result (info, - GUINT_TO_POINTER (priv->allowed_mode), - NULL); - } - - if (r) - g_regex_unref (r); - if (match_info) - g_match_info_free (match_info); - g_free (mode_str); - g_free (prefer_str); - - mm_callback_info_schedule (info); -} - -static void -get_allowed_mode (MMGenericGsm *gsm, - MMModemUIntFn callback, - gpointer user_data) -{ - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (gsm); - MMCallbackInfo *info; - - info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); - - /* For 3G devices, query WWSM status */ - if (priv->supported_ms_classes & WAVECOM_MS_CLASS_A) { - MMAtSerialPort *port; - - port = mm_generic_gsm_get_best_at_port (gsm, &info->error); - if (!port) { - mm_callback_info_schedule (info); - return; - } - - mm_at_serial_port_queue_command (port, "+WWSM?", 3, get_allowed_mode_cb, info); - return; - } - - /* For 2G devices, just return cached value */ - mm_callback_info_set_result (info, - GUINT_TO_POINTER (priv->allowed_mode), - NULL); - mm_callback_info_schedule (info); -} - -static void -set_allowed_mode_cb (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) - info->error = g_error_copy (error); - else { - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - - priv->allowed_mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "new-mode")); - } - - mm_callback_info_schedule (info); -} - -static void -set_allowed_mode (MMGenericGsm *gsm, - MMModemGsmAllowedMode mode, - MMModemFn callback, - gpointer user_data) -{ - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (gsm); - MMCallbackInfo *info; - - info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); - - /* For 3G devices, go on with WWSM */ - if (priv->supported_ms_classes & WAVECOM_MS_CLASS_A) { - MMAtSerialPort *port; - GString *cmd; - gint net = -1; - gint prefer = -1; - - /* Get port */ - port = mm_generic_gsm_get_best_at_port (gsm, &info->error); - if (!port) { - mm_callback_info_schedule (info); - return; - } - - mm_callback_info_set_data (info, - "new-mode", - GUINT_TO_POINTER (mode), - NULL); - - switch (mode) { - case MM_MODEM_GSM_ALLOWED_MODE_ANY: - net = 2; - prefer = 0; - break; - case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: - net = 2; - prefer = 1; - break; - case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: - net = 2; - prefer = 2; - break; - case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: - net = 0; - break; - case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: - net = 1; - break; - } - - cmd = g_string_new ("+WWSM="); - g_string_append_printf (cmd, "%d", net); - if (net == 2) - g_string_append_printf (cmd, ",%d", prefer); - mm_at_serial_port_queue_command (port, cmd->str, 3, set_allowed_mode_cb, info); - g_string_free (cmd, TRUE); - - return; - } - - /* For non-3G devices, allow only 2G-related allowed modes */ - switch (mode) { - case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: - case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: - case MM_MODEM_GSM_ALLOWED_MODE_ANY: - priv->allowed_mode = mode; - break; - default: - info->error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Cannot set desired allowed mode, " - "not a 3G device"); - break; - } - - mm_callback_info_schedule (info); -} - -static void -enable_complete (MMGenericGsm *gsm, - GError *error, - MMCallbackInfo *info) -{ - /* Do NOT chain up parent do_enable_power_up_done(), as it actually ignores - * all errors. */ - - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); -} - -static void -set_highest_ms_class_cb (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - guint new_class; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) { - enable_complete (MM_GENERIC_GSM (info->modem), error, info); - return; - } - - new_class = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "new-class")); - if (new_class) { - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - - priv->current_ms_class = new_class; - } - - /* All done without errors! */ - mm_dbg ("[4/4] All done"); - enable_complete (MM_GENERIC_GSM (info->modem), NULL, info); -} - -static void -set_highest_ms_class (MMAtSerialPort *port, - MMCallbackInfo *info) -{ - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - guint new_class = 0; - - if (priv->supported_ms_classes & WAVECOM_MS_CLASS_A) { - if (priv->current_ms_class != WAVECOM_MS_CLASS_A) { - /* A is supported but is not currently selected, switch to A */ - new_class = WAVECOM_MS_CLASS_A; - } - } else if (priv->supported_ms_classes & WAVECOM_MS_CLASS_B) { - if (priv->current_ms_class != WAVECOM_MS_CLASS_B) { - /* B is supported but is not currently selected, switch to B */ - new_class = WAVECOM_MS_CLASS_B; - } - } else if (priv->supported_ms_classes & WAVECOM_MS_CLASS_CG) { - if (priv->current_ms_class != WAVECOM_MS_CLASS_CG) { - /* CG is supported but is not currently selected, switch to CG */ - new_class = WAVECOM_MS_CLASS_CG; - } - } - - if (new_class) { - const gchar *new_class_str; - gchar *cmd; - - new_class_str = wavecom_ms_class_to_str (new_class); - mm_dbg ("Changing mobile station class to: %s", new_class_str); - mm_callback_info_set_data (info, - "new-class", - GUINT_TO_POINTER (new_class), - NULL); - cmd = g_strdup_printf ("+CGCLASS=%s", new_class_str); - mm_at_serial_port_queue_command (port, cmd, 3, set_highest_ms_class_cb, info); - g_free (cmd); - return; - } - - /* if no need to change station class, then just go on */ - mm_dbg ("No need to change mobile station class"); - set_highest_ms_class_cb (port, NULL, NULL, info); -} - -static void -get_current_ms_class_cb (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = user_data; - MMModemWavecomGsmPrivate *priv; - const gchar *p; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) { - enable_complete (MM_GENERIC_GSM (info->modem), error, info); - return; - } - - priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - - p = mm_strip_tag (response->str, "+CGCLASS:"); - - if (strncmp (p, - WAVECOM_MS_CLASS_A_IDSTR, - strlen (WAVECOM_MS_CLASS_A_IDSTR)) == 0) { - mm_dbg ("Modem configured as a Class A mobile station"); - priv->current_ms_class = WAVECOM_MS_CLASS_A; - } else if (strncmp (p, - WAVECOM_MS_CLASS_B_IDSTR, - strlen (WAVECOM_MS_CLASS_B_IDSTR)) == 0) { - mm_dbg ("Modem configured as a Class B mobile station"); - priv->current_ms_class = WAVECOM_MS_CLASS_B; - } else if (strncmp (p, - WAVECOM_MS_CLASS_CG_IDSTR, - strlen (WAVECOM_MS_CLASS_CG_IDSTR)) == 0) { - mm_dbg ("Modem configured as a Class CG mobile station"); - priv->current_ms_class = WAVECOM_MS_CLASS_CG; - } else if (strncmp (p, - WAVECOM_MS_CLASS_CC_IDSTR, - strlen (WAVECOM_MS_CLASS_CC_IDSTR)) == 0) { - mm_dbg ("Modem configured as a Class CC mobile station"); - priv->current_ms_class = WAVECOM_MS_CLASS_CC; - } else { - GError *inner_error; - - inner_error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Unknown mobile station class: '%s'", - p); - enable_complete (MM_GENERIC_GSM (info->modem), inner_error, info); - g_error_free (inner_error); - return; - } - - /* Next, set highest mobile station class possible */ - mm_dbg ("[3/4] Ensuring highest MS class..."); - set_highest_ms_class (port, info); -} - -static void -get_supported_ms_classes_cb (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = user_data; - MMModemWavecomGsmPrivate *priv; - const gchar *p; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) { - enable_complete (MM_GENERIC_GSM (info->modem), error, info); - return; - } - - priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (info->modem); - - /* Reset currently supported MS classes */ - priv->supported_ms_classes = 0; - - p = mm_strip_tag (response->str, "+CGCLASS:"); - - if (strstr (p, WAVECOM_MS_CLASS_A_IDSTR)) { - mm_dbg ("Modem supports Class A mobile station"); - priv->supported_ms_classes |= WAVECOM_MS_CLASS_A; - } - - if (strstr (p, WAVECOM_MS_CLASS_B_IDSTR)) { - mm_dbg ("Modem supports Class B mobile station"); - priv->supported_ms_classes |= WAVECOM_MS_CLASS_B; - } - - if (strstr (p, WAVECOM_MS_CLASS_CG_IDSTR)) { - mm_dbg ("Modem supports Class CG mobile station"); - priv->supported_ms_classes |= WAVECOM_MS_CLASS_CG; - } - - if (strstr (p, WAVECOM_MS_CLASS_CC_IDSTR)) { - mm_dbg ("Modem supports Class CC mobile station"); - priv->supported_ms_classes |= WAVECOM_MS_CLASS_CC; - } - - /* If none received, error */ - if (!priv->supported_ms_classes) { - GError *inner_error; - - inner_error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Couldn't get supported mobile station classes"); - enable_complete (MM_GENERIC_GSM (info->modem), inner_error, info); - g_error_free (inner_error); - return; - } - - /* Next, query for current MS class */ - mm_dbg ("[2/4] Getting current MS class..."); - mm_at_serial_port_queue_command (port, "+CGCLASS?", 3, get_current_ms_class_cb, info); -} - -static void -do_enable_power_up_done (MMGenericGsm *gsm, - GString *response, - GError *error, - MMCallbackInfo *info) -{ - MMAtSerialPort *port; - GError *inner_error = NULL; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - if (error) { - enable_complete (gsm, error, info); - return; - } - - /* Get port */ - port = mm_generic_gsm_get_best_at_port (gsm, &inner_error); - if (!port) { - enable_complete (gsm, inner_error, info); - g_error_free (inner_error); - return; - } - - mm_dbg ("[1/4] Getting supported MS classes..."); - mm_at_serial_port_queue_command (port, "+CGCLASS=?", 3, get_supported_ms_classes_cb, info); -} - -static void -get_current_functionality_status_cb (MMAtSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = user_data; - guint needed = FALSE; - - /* If the modem has already been removed, return without - * scheduling callback */ - if (mm_callback_info_check_modem_removed (info)) - return; - - /* On error, just assume we don't need the power-up command */ - if (!error) { - const gchar *p; - - p = mm_strip_tag (response->str, "+CFUN:"); - if (p && *p == '1') { - /* If reported functionality status is '1', then we do not need to - * issue the power-up command. Otherwise, do it. */ - mm_dbg ("Already in full functionality status, skipping power-up command"); - } else { - needed = TRUE; - mm_warn ("Not in full functionality status, power-up command is needed. " - "Note that it may reboot the modem."); - } - } else - mm_warn ("Failed checking if power-up command is needed: '%s'. " - "Will assume it isn't.", - error->message); - - /* Set result and schedule */ - mm_callback_info_set_result (info, - GUINT_TO_POINTER (needed), - NULL); - mm_callback_info_schedule (info); -} - -static void -do_enable_power_up_check_needed (MMGenericGsm *self, - MMModemUIntFn callback, - gpointer user_data) -{ - MMAtSerialPort *primary; - MMCallbackInfo *info; - - info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data); - - /* Get port */ - primary = mm_generic_gsm_get_at_port (self, MM_AT_PORT_FLAG_PRIMARY); - g_assert (primary); - - /* Get current functionality status */ - mm_dbg ("Getting current functionality status..."); - mm_at_serial_port_queue_command (primary, "+CFUN?", 3, get_current_functionality_status_cb, info); -} - -/*****************************************************************************/ - -static void -modem_gsm_network_init (MMModemGsmNetwork *network_class) -{ - network_class->set_band = set_band; - network_class->get_band = get_band; -} - -static void -mm_modem_wavecom_gsm_init (MMModemWavecomGsm *self) -{ - MMModemWavecomGsmPrivate *priv = MM_MODEM_WAVECOM_GSM_GET_PRIVATE (self); - - /* Set defaults */ - priv->supported_ms_classes = 0; /* This is a bitmask, so empty */ - priv->current_ms_class = WAVECOM_MS_CLASS_UNKNOWN; - priv->allowed_mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; - priv->current_bands = 0; /* This is a bitmask, so empty */ -} - -static void -mm_modem_wavecom_gsm_class_init (MMModemWavecomGsmClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (MMModemWavecomGsmPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - - g_object_class_override_property (object_class, - MM_GENERIC_GSM_PROP_POWER_UP_CMD, - MM_GENERIC_GSM_POWER_UP_CMD); - - g_object_class_override_property (object_class, - MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD, - MM_GENERIC_GSM_FLOW_CONTROL_CMD); - - g_object_class_override_property (object_class, - MM_GENERIC_GSM_PROP_POWER_DOWN_CMD, - MM_GENERIC_GSM_POWER_DOWN_CMD); - - gsm_class->port_grabbed = port_grabbed; - gsm_class->do_enable_power_up_check_needed = do_enable_power_up_check_needed; - gsm_class->do_enable_power_up_done = do_enable_power_up_done; - gsm_class->set_allowed_mode = set_allowed_mode; - gsm_class->get_allowed_mode = get_allowed_mode; - gsm_class->get_access_technology = get_access_technology; -} -
diff --git a/plugins/mm-modem-wavecom-gsm.h b/plugins/mm-modem-wavecom-gsm.h deleted file mode 100644 index 25540ad..0000000 --- a/plugins/mm-modem-wavecom-gsm.h +++ /dev/null
@@ -1,45 +0,0 @@ -/* -*- 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) 2011 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#ifndef MM_MODEM_WAVECOM_GSM_H -#define MM_MODEM_WAVECOM_GSM_H - -#include "mm-generic-gsm.h" - -#define MM_TYPE_MODEM_WAVECOM_GSM (mm_modem_wavecom_gsm_get_type ()) -#define MM_MODEM_WAVECOM_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_WAVECOM_GSM, MMModemWavecomGsm)) -#define MM_MODEM_WAVECOM_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_WAVECOM_AIRLINK_GSM, MMModemWavecomGsmClass)) -#define MM_IS_MODEM_WAVECOM_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_WAVECOM_AIRLINK_GSM)) -#define MM_IS_MODEM_WAVECOM_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_WAVECOM_AIRLINK_GSM)) -#define MM_MODEM_WAVECOM_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_WAVECOM_AIRLINK_GSM, MMModemWavecomGsmClass)) - -typedef struct { - MMGenericGsm parent; -} MMModemWavecomGsm; - -typedef struct { - MMGenericGsmClass parent; -} MMModemWavecomGsmClass; - -GType mm_modem_wavecom_gsm_get_type (void); - -MMModem *mm_modem_wavecom_gsm_new (const char *device, - const char *driver, - const char *plugin_name, - guint32 vendor, - guint32 product); - -#endif /* MM_MODEM_WAVECOM_GSM_H */
diff --git a/plugins/mm-plugin-wavecom.c b/plugins/mm-plugin-wavecom.c deleted file mode 100644 index 3bd82cb..0000000 --- a/plugins/mm-plugin-wavecom.c +++ /dev/null
@@ -1,168 +0,0 @@ -/* -*- 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. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Copyright (C) 2011 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@lanedo.com> - */ - -#include <string.h> -#include <gmodule.h> -#include "mm-plugin-wavecom.h" -#include "mm-modem-wavecom-gsm.h" - -G_DEFINE_TYPE (MMPluginWavecom, mm_plugin_wavecom, MM_TYPE_PLUGIN_BASE) - -int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION; -int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION; - -G_MODULE_EXPORT MMPlugin * -mm_plugin_create (void) -{ - return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_WAVECOM, - MM_PLUGIN_BASE_NAME, "Wavecom", - NULL)); -} - -static guint32 -get_level_for_capabilities (guint32 capabilities) -{ - if (capabilities & MM_PLUGIN_BASE_PORT_CAP_GSM) - return 10; - return 0; -} - -static void -probe_result (MMPluginBase *base, - MMPluginBaseSupportsTask *task, - guint32 capabilities, - gpointer user_data) -{ - mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities)); -} - -static MMPluginSupportsResult -supports_port (MMPluginBase *base, - MMModem *existing, - MMPluginBaseSupportsTask *task) -{ - GUdevDevice *port; - 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; - - /* Vendor: Wavecom */ - if (vendor != 0x114f) - return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; - - /* Check if a previous probing was already launched in this port */ - if (mm_plugin_base_supports_task_propagate_cached (task)) { - guint32 level; - - /* A previous probing was already done, use its results */ - level = get_level_for_capabilities (mm_plugin_base_supports_task_get_probed_capabilities (task)); - 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, 100000, NULL)) - return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS; - - return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; -} - -static MMModem * -grab_port (MMPluginBase *base, - MMModem *existing, - MMPluginBaseSupportsTask *task, - GError **error) -{ - GUdevDevice *port = NULL; - MMModem *modem = NULL; - const char *name, *subsys, *sysfs_path; - guint32 caps; - guint16 vendor = 0, product = 0; - MMPortType ptype; - - port = mm_plugin_base_supports_task_get_port (task); - g_assert (port); - - subsys = g_udev_device_get_subsystem (port); - name = g_udev_device_get_name (port); - - if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) { - g_set_error (error, 0, 0, "Could not get modem product ID."); - return NULL; - } - - caps = mm_plugin_base_supports_task_get_probed_capabilities (task); - ptype = mm_plugin_base_probed_capabilities_to_port_type (caps); - sysfs_path = mm_plugin_base_supports_task_get_physdev_path (task); - if (!existing) { - if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) { - modem = mm_modem_wavecom_gsm_new (sysfs_path, - mm_plugin_base_supports_task_get_driver (task), - mm_plugin_get_name (MM_PLUGIN (base)), - vendor, - product); - } - - if (modem) { - if (!mm_modem_grab_port (modem, subsys, name, ptype, MM_AT_PORT_FLAG_NONE, NULL, error)) { - g_object_unref (modem); - return NULL; - } - } - } else if (get_level_for_capabilities (caps)) { - modem = existing; - if (!mm_modem_grab_port (modem, subsys, name, ptype, MM_AT_PORT_FLAG_NONE, NULL, error)) - return NULL; - } - - return modem; -} - -/*****************************************************************************/ - -static void -mm_plugin_wavecom_init (MMPluginWavecom *self) -{ - g_signal_connect (self, "probe-result", G_CALLBACK (probe_result), NULL); -} - -static void -mm_plugin_wavecom_class_init (MMPluginWavecomClass *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/novatel/mm-broadband-bearer-novatel.c b/plugins/novatel/mm-broadband-bearer-novatel.c index 20f87c1..a3482ae 100644 --- a/plugins/novatel/mm-broadband-bearer-novatel.c +++ b/plugins/novatel/mm-broadband-bearer-novatel.c
@@ -36,36 +36,21 @@ G_DEFINE_TYPE (MMBroadbandBearerNovatel, mm_broadband_bearer_novatel, MM_TYPE_BROADBAND_BEARER); -enum { - PROP_0, - PROP_USER, - PROP_PASSWORD, - PROP_LAST -}; - -static GParamSpec *properties[PROP_LAST]; - /*****************************************************************************/ - - struct _MMBroadbandBearerNovatelPrivate { /* timeout id for checking whether we're still connected */ guint connection_poller; - /* Username for authenticating to APN */ - gchar *user; - /* Password for authenticating to APN */ - gchar *password; }; typedef struct { - MMBroadbandBearer *self; + MMBroadbandBearerNovatel *self; MMBaseModem *modem; MMAtSerialPort *primary; MMPort *data; GCancellable *cancellable; GSimpleAsyncResult *result; - int retries; + gint retries; } DetailedConnectContext; static DetailedConnectContext * @@ -143,13 +128,14 @@ if (!result) { mm_warn ("QMI connection status failed: %s", error->message); g_error_free (error); - } else { - result = mm_strip_tag (result, "$NWQMISTATUS:"); - if (g_strrstr(result, "QMI State: DISCONNECTED")) { - mm_bearer_report_disconnection (MM_BEARER (bearer)); - g_source_remove (bearer->priv->connection_poller); - bearer->priv->connection_poller = 0; - } + return; + } + + result = mm_strip_tag (result, "$NWQMISTATUS:"); + if (g_strrstr (result, "QMI State: DISCONNECTED")) { + mm_bearer_report_disconnection (MM_BEARER (bearer)); + g_source_remove (bearer->priv->connection_poller); + bearer->priv->connection_poller = 0; } } @@ -157,6 +143,7 @@ poll_connection (MMBroadbandBearerNovatel *bearer) { MMBaseModem *modem = NULL; + g_object_get (MM_BEARER (bearer), MM_BEARER_MODEM, &modem, NULL); @@ -168,6 +155,7 @@ (GAsyncReadyCallback)poll_connection_ready, bearer); g_object_unref (modem); + return TRUE; } @@ -185,35 +173,41 @@ if (!result) { mm_warn ("QMI connection status failed: %s", error->message); g_simple_async_result_take_error (ctx->result, error); - } else { - result = mm_strip_tag (result, "$NWQMISTATUS:"); - if (g_strrstr(result, "QMI State: CONNECTED")) { - MMBearerIpConfig *config; - MMBroadbandBearerNovatel *bearer = MM_BROADBAND_BEARER_NOVATEL (ctx->self); - mm_dbg("Connected"); - bearer->priv->connection_poller = g_timeout_add_seconds (CONNECTION_CHECK_TIMEOUT_SEC, - (GSourceFunc)poll_connection, - bearer); - config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); - g_simple_async_result_set_op_res_gpointer (ctx->result, - config, - (GDestroyNotify)g_object_unref); - } else { - mm_dbg("Error: '%s'", result); - if (ctx->retries > 0) { - ctx->retries--; - mm_dbg("Retrying status check in a second. %d retries left.", - ctx->retries); - g_timeout_add_seconds(1, (GSourceFunc)connect_3gpp_qmistatus, ctx); - return; - } - g_simple_async_result_set_error (ctx->result, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "%s", result); - } + detailed_connect_context_complete_and_free (ctx); + return; } + + result = mm_strip_tag (result, "$NWQMISTATUS:"); + if (g_strrstr (result, "QMI State: CONNECTED")) { + MMBearerIpConfig *config; + + mm_dbg("Connected"); + ctx->self->priv->connection_poller = g_timeout_add_seconds (CONNECTION_CHECK_TIMEOUT_SEC, + (GSourceFunc)poll_connection, + ctx->self); + config = mm_bearer_ip_config_new (); + mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); + g_simple_async_result_set_op_res_gpointer (ctx->result, + config, + (GDestroyNotify)g_object_unref); + detailed_connect_context_complete_and_free (ctx); + return; + } + + mm_dbg ("Error: '%s'", result); + if (ctx->retries > 0) { + ctx->retries--; + mm_dbg ("Retrying status check in a second. %d retries left.", + ctx->retries); + g_timeout_add_seconds (1, (GSourceFunc)connect_3gpp_qmistatus, ctx); + return; + } + + /* Already exhausted all retries */ + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "%s", result); detailed_connect_context_complete_and_free (ctx); } @@ -255,7 +249,7 @@ * happened. Instead, we need to poll the modem to see if it's * ready. */ - g_timeout_add_seconds(1, (GSourceFunc)connect_3gpp_qmistatus, ctx); + g_timeout_add_seconds (1, (GSourceFunc)connect_3gpp_qmistatus, ctx); } static void @@ -268,9 +262,9 @@ GAsyncReadyCallback callback, gpointer user_data) { - MMBroadbandBearerNovatel *self = MM_BROADBAND_BEARER_NOVATEL (bearer); DetailedConnectContext *ctx; gchar *command, *apn, *user, *password; + MMBearerProperties *config; ctx = detailed_connect_context_new (bearer, modem, @@ -280,9 +274,10 @@ callback, user_data); - apn = mm_at_serial_port_quote_string (mm_broadband_bearer_get_3gpp_apn (bearer)); - user = mm_at_serial_port_quote_string (self->priv->user); - password = mm_at_serial_port_quote_string (self->priv->password); + config = mm_bearer_peek_config (MM_BEARER (bearer)); + apn = mm_at_serial_port_quote_string (mm_bearer_properties_get_apn (config)); + user = mm_at_serial_port_quote_string (mm_bearer_properties_get_user (config)); + password = mm_at_serial_port_quote_string (mm_bearer_properties_get_password (config)); command = g_strdup_printf ("$NWQMICONNECT=,,,,,,%s,,,%s,%s", apn, user, password); g_free (apn); @@ -298,7 +293,6 @@ g_free (command); } - typedef struct { MMBroadbandBearer *self; MMBaseModem *modem; @@ -308,7 +302,6 @@ GSimpleAsyncResult *result; } DetailedDisconnectContext; - static DetailedDisconnectContext * detailed_disconnect_context_new (MMBroadbandBearer *self, MMBroadbandModem *modem, @@ -366,21 +359,24 @@ result = mm_base_modem_at_command_finish (MM_BASE_MODEM (modem), res, &error); - - g_simple_async_result_set_op_res_gboolean (ctx->result, FALSE); if (error) { mm_dbg("QMI connection status failed: %s", error->message); g_error_free (error); } result = mm_strip_tag (result, "$NWQMISTATUS:"); - if (g_strrstr(result, "QMI State: DISCONNECTED")) + if (result && g_strrstr (result, "QMI State: DISCONNECTED")) g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + else + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Error checking if disconnected (%s)", + result ? result : "no result"); detailed_disconnect_context_complete_and_free (ctx); } - static void disconnect_3gpp_check_status (MMBaseModem *modem, GAsyncResult *res, @@ -435,14 +431,11 @@ ctx); /* user_data */ } - static void finalize (GObject *object) { MMBroadbandBearerNovatel *self = MM_BROADBAND_BEARER_NOVATEL (object); - g_free (self->priv->user); - g_free (self->priv->password); if (self->priv->connection_poller) g_source_remove (self->priv->connection_poller); @@ -450,94 +443,12 @@ } static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerNovatel *self = MM_BROADBAND_BEARER_NOVATEL (object); - - switch (prop_id) { - case PROP_USER: - g_free (self->priv->user); - self->priv->user = g_value_dup_string (value); - break; - case PROP_PASSWORD: - g_free (self->priv->password); - self->priv->password = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerNovatel *self = MM_BROADBAND_BEARER_NOVATEL (object); - - switch (prop_id) { - case PROP_USER: - g_value_set_string (value, self->priv->user); - break; - case PROP_PASSWORD: - g_value_set_string (value, self->priv->password); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -cmp_properties (MMBearer *bearer, - MMBearerProperties *properties) -{ - MMBroadbandBearerNovatel *self = MM_BROADBAND_BEARER_NOVATEL (bearer); - - return ((mm_broadband_bearer_get_allow_roaming (MM_BROADBAND_BEARER (self)) == - mm_bearer_properties_get_allow_roaming (properties)) && - (!g_strcmp0 (mm_broadband_bearer_get_ip_type (MM_BROADBAND_BEARER (self)), - mm_bearer_properties_get_ip_type (properties))) && - (!g_strcmp0 (mm_broadband_bearer_get_3gpp_apn (MM_BROADBAND_BEARER (self)), - mm_bearer_properties_get_apn (properties))) && - (!g_strcmp0 (self->priv->user, - mm_bearer_properties_get_user (properties))) && - (!g_strcmp0 (self->priv->password, - mm_bearer_properties_get_password (properties)))); -} - -static MMBearerProperties * -expose_properties (MMBearer *bearer) -{ - MMBroadbandBearerNovatel *self = MM_BROADBAND_BEARER_NOVATEL (bearer); - MMBearerProperties *properties; - - properties = mm_bearer_properties_new (); - mm_bearer_properties_set_apn (properties, - mm_broadband_bearer_get_3gpp_apn (MM_BROADBAND_BEARER (self))); - mm_bearer_properties_set_ip_type (properties, - mm_broadband_bearer_get_ip_type (MM_BROADBAND_BEARER (self))); - mm_bearer_properties_set_allow_roaming (properties, - mm_broadband_bearer_get_allow_roaming (MM_BROADBAND_BEARER (self))); - mm_bearer_properties_set_user (properties, self->priv->user); - mm_bearer_properties_set_password (properties, self->priv->user); - return properties; -} - -static void mm_broadband_bearer_novatel_init (MMBroadbandBearerNovatel *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), MM_TYPE_BROADBAND_BEARER_NOVATEL, MMBroadbandBearerNovatelPrivate); - self->priv->user = NULL; - self->priv->password = NULL; self->priv->connection_poller = 0; } @@ -545,38 +456,16 @@ mm_broadband_bearer_novatel_class_init (MMBroadbandBearerNovatelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBearerClass *bearer_class = MM_BEARER_CLASS (klass); MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); g_type_class_add_private (object_class, sizeof (MMBroadbandBearerNovatelPrivate)); - object_class->get_property = get_property; - object_class->set_property = set_property; object_class->finalize = finalize; - bearer_class->cmp_properties = cmp_properties; - bearer_class->expose_properties = expose_properties; - broadband_bearer_class->connect_3gpp = connect_3gpp; broadband_bearer_class->connect_3gpp_finish = connect_3gpp_finish; broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; - - properties[PROP_USER] = - g_param_spec_string (MM_BROADBAND_BEARER_NOVATEL_USER, - "User", - "Username to authenticate to APN", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_USER, properties[PROP_USER]); - - properties[PROP_PASSWORD] = - g_param_spec_string (MM_BROADBAND_BEARER_NOVATEL_PASSWORD, - "Password", - "Password to authenticate to APN", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_PASSWORD, properties[PROP_PASSWORD]); } MMBearer * @@ -599,11 +488,12 @@ return MM_BEARER (bearer); } -void mm_broadband_bearer_novatel_new (MMBroadbandModemNovatel *modem, - MMBearerProperties *properties, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +void +mm_broadband_bearer_novatel_new (MMBroadbandModemNovatel *modem, + MMBearerProperties *config, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { g_async_initable_new_async ( MM_TYPE_BROADBAND_BEARER_NOVATEL, @@ -612,10 +502,6 @@ callback, user_data, MM_BEARER_MODEM, modem, - MM_BROADBAND_BEARER_3GPP_APN, mm_bearer_properties_get_apn (properties), - MM_BROADBAND_BEARER_IP_TYPE, mm_bearer_properties_get_ip_type (properties), - MM_BROADBAND_BEARER_ALLOW_ROAMING, mm_bearer_properties_get_allow_roaming (properties), - MM_BROADBAND_BEARER_NOVATEL_USER, mm_bearer_properties_get_user (properties), - MM_BROADBAND_BEARER_NOVATEL_PASSWORD, mm_bearer_properties_get_password (properties), + MM_BEARER_CONFIG, config, NULL); }
diff --git a/plugins/option/mm-broadband-bearer-hso.c b/plugins/option/mm-broadband-bearer-hso.c index 1d8e1d1..d2cfd91 100644 --- a/plugins/option/mm-broadband-bearer-hso.c +++ b/plugins/option/mm-broadband-bearer-hso.c
@@ -36,20 +36,8 @@ G_DEFINE_TYPE (MMBroadbandBearerHso, mm_broadband_bearer_hso, MM_TYPE_BROADBAND_BEARER); -enum { - PROP_0, - PROP_USER, - PROP_PASSWORD, - PROP_LAST -}; - -static GParamSpec *properties[PROP_LAST]; - struct _MMBroadbandBearerHsoPrivate { - gchar *user; - gchar *password; guint auth_idx; - gpointer connect_pending; guint connect_pending_id; gulong connect_cancellable_id; @@ -544,6 +532,8 @@ authenticate (Dial3gppContext *ctx) { gchar *command; + const gchar *user; + const gchar *password; if (!auth_commands[ctx->auth_idx]) { g_simple_async_result_set_error (ctx->result, @@ -554,8 +544,11 @@ return; } + user = mm_bearer_properties_get_user (mm_bearer_peek_config (MM_BEARER (ctx->self))); + password = mm_bearer_properties_get_password (mm_bearer_peek_config (MM_BEARER (ctx->self))); + /* Both user and password are required; otherwise firmware returns an error */ - if (!ctx->self->priv->user || !ctx->self->priv->password) + if (!user || !password) command = g_strdup_printf ("%s=%d,0", auth_commands[ctx->auth_idx], ctx->cid); @@ -563,8 +556,8 @@ command = g_strdup_printf ("%s=%d,1,\"%s\",\"%s\"", auth_commands[ctx->auth_idx], ctx->cid, - ctx->self->priv->password, - ctx->self->priv->user); + password, + user); mm_base_modem_at_command_full (ctx->modem, ctx->primary, @@ -683,44 +676,6 @@ /*****************************************************************************/ -static gboolean -cmp_properties (MMBearer *self, - MMBearerProperties *properties) -{ - MMBroadbandBearerHso *hso = MM_BROADBAND_BEARER_HSO (self); - - return ((mm_broadband_bearer_get_allow_roaming (MM_BROADBAND_BEARER (self)) == - mm_bearer_properties_get_allow_roaming (properties)) && - (!g_strcmp0 (mm_broadband_bearer_get_ip_type (MM_BROADBAND_BEARER (self)), - mm_bearer_properties_get_ip_type (properties))) && - (!g_strcmp0 (mm_broadband_bearer_get_3gpp_apn (MM_BROADBAND_BEARER (self)), - mm_bearer_properties_get_apn (properties))) && - (!g_strcmp0 (hso->priv->user, - mm_bearer_properties_get_user (properties))) && - (!g_strcmp0 (hso->priv->password, - mm_bearer_properties_get_password (properties)))); -} - -static MMBearerProperties * -expose_properties (MMBearer *self) -{ - MMBroadbandBearerHso *hso = MM_BROADBAND_BEARER_HSO (self); - MMBearerProperties *properties; - - properties = mm_bearer_properties_new (); - mm_bearer_properties_set_apn (properties, - mm_broadband_bearer_get_3gpp_apn (MM_BROADBAND_BEARER (self))); - mm_bearer_properties_set_ip_type (properties, - mm_broadband_bearer_get_ip_type (MM_BROADBAND_BEARER (self))); - mm_bearer_properties_set_allow_roaming (properties, - mm_broadband_bearer_get_allow_roaming (MM_BROADBAND_BEARER (self))); - mm_bearer_properties_set_user (properties, hso->priv->user); - mm_bearer_properties_set_password (properties, hso->priv->user); - return properties; -} - -/*****************************************************************************/ - MMBearer * mm_broadband_bearer_hso_new_finish (GAsyncResult *res, GError **error) @@ -743,7 +698,7 @@ void mm_broadband_bearer_hso_new (MMBroadbandModemHso *modem, - MMBearerProperties *properties, + MMBearerProperties *config, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) @@ -755,59 +710,11 @@ callback, user_data, MM_BEARER_MODEM, modem, - MM_BROADBAND_BEARER_3GPP_APN, mm_bearer_properties_get_apn (properties), - MM_BROADBAND_BEARER_IP_TYPE, mm_bearer_properties_get_ip_type (properties), - MM_BROADBAND_BEARER_ALLOW_ROAMING, mm_bearer_properties_get_allow_roaming (properties), - MM_BROADBAND_BEARER_HSO_USER, mm_bearer_properties_get_user (properties), - MM_BROADBAND_BEARER_HSO_PASSWORD, mm_bearer_properties_get_password (properties), + MM_BEARER_CONFIG, config, NULL); } static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerHso *self = MM_BROADBAND_BEARER_HSO (object); - - switch (prop_id) { - case PROP_USER: - g_free (self->priv->user); - self->priv->user = g_value_dup_string (value); - break; - case PROP_PASSWORD: - g_free (self->priv->password); - self->priv->password = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearerHso *self = MM_BROADBAND_BEARER_HSO (object); - - switch (prop_id) { - case PROP_USER: - g_value_set_string (value, self->priv->user); - break; - case PROP_PASSWORD: - g_value_set_string (value, self->priv->password); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void mm_broadband_bearer_hso_init (MMBroadbandBearerHso *self) { /* Initialize private data */ @@ -817,52 +724,17 @@ } static void -finalize (GObject *object) -{ - MMBroadbandBearerHso *self = MM_BROADBAND_BEARER_HSO (object); - - g_free (self->priv->user); - g_free (self->priv->password); - - G_OBJECT_CLASS (mm_broadband_bearer_hso_parent_class)->finalize (object); -} - -static void mm_broadband_bearer_hso_class_init (MMBroadbandBearerHsoClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - MMBearerClass *bearer_class = MM_BEARER_CLASS (klass); MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass); g_type_class_add_private (object_class, sizeof (MMBroadbandBearerHsoPrivate)); - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - bearer_class->cmp_properties = cmp_properties; - bearer_class->expose_properties = expose_properties; - broadband_bearer_class->dial_3gpp = dial_3gpp; broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish; broadband_bearer_class->get_ip_config_3gpp = get_ip_config_3gpp; broadband_bearer_class->get_ip_config_3gpp_finish = get_ip_config_3gpp_finish; broadband_bearer_class->disconnect_3gpp = disconnect_3gpp; broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish; - - properties[PROP_USER] = - g_param_spec_string (MM_BROADBAND_BEARER_HSO_USER, - "User", - "Username to use to authenticate the connection", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_USER, properties[PROP_USER]); - - properties[PROP_PASSWORD] = - g_param_spec_string (MM_BROADBAND_BEARER_HSO_PASSWORD, - "Password", - "Password to use to authenticate the connection", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_PASSWORD, properties[PROP_PASSWORD]); }
diff --git a/plugins/option/mm-broadband-bearer-hso.h b/plugins/option/mm-broadband-bearer-hso.h index 4773d46..24e7aa3 100644 --- a/plugins/option/mm-broadband-bearer-hso.h +++ b/plugins/option/mm-broadband-bearer-hso.h
@@ -31,9 +31,6 @@ #define MM_IS_BROADBAND_BEARER_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_HSO)) #define MM_BROADBAND_BEARER_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_HSO, MMBroadbandBearerHsoClass)) -#define MM_BROADBAND_BEARER_HSO_USER "broadband-bearer-hso-user" -#define MM_BROADBAND_BEARER_HSO_PASSWORD "broadband-bearer-hso-password" - typedef enum { MM_BROADBAND_BEARER_HSO_CONNECTION_STATUS_UNKNOWN, MM_BROADBAND_BEARER_HSO_CONNECTION_STATUS_CONNECTED, @@ -58,7 +55,7 @@ /* Default 3GPP bearer creation implementation */ void mm_broadband_bearer_hso_new (MMBroadbandModemHso *modem, - MMBearerProperties *properties, + MMBearerProperties *config, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
diff --git a/plugins/wavecom/mm-broadband-modem-wavecom.c b/plugins/wavecom/mm-broadband-modem-wavecom.c new file mode 100644 index 0000000..9be84c0 --- /dev/null +++ b/plugins/wavecom/mm-broadband-modem-wavecom.c
@@ -0,0 +1,1231 @@ +/* -*- 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) 2011 Ammonit Measurement GmbH + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + * Author: Aleksander Morgado <aleksander@lanedo.com> + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include <libmm-common.h> + +#include "ModemManager.h" +#include "mm-log.h" +#include "mm-serial-parsers.h" +#include "mm-modem-helpers.h" +#include "mm-iface-modem.h" +#include "mm-iface-modem-3gpp.h" +#include "mm-base-modem-at.h" +#include "mm-broadband-modem-wavecom.h" + +static void iface_modem_init (MMIfaceModem *iface); + +G_DEFINE_TYPE_EXTENDED (MMBroadbandModemWavecom, mm_broadband_modem_wavecom, MM_TYPE_BROADBAND_MODEM, 0, + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)) + +#define WAVECOM_MS_CLASS_CC_IDSTR "\"CC\"" +#define WAVECOM_MS_CLASS_CG_IDSTR "\"CG\"" +#define WAVECOM_MS_CLASS_B_IDSTR "\"B\"" +#define WAVECOM_MS_CLASS_A_IDSTR "\"A\"" + +/* Setup relationship between 2G bands in the modem (identified by a + * single digit in ASCII) and the bitmask in ModemManager. */ +typedef struct { + gchar wavecom_band; + guint n_mm_bands; + MMModemBand mm_bands[4]; +} WavecomBand2G; +static const WavecomBand2G bands_2g[] = { + { '0', 1, { MM_MODEM_BAND_G850, 0, 0, 0 }}, + { '1', 1, { MM_MODEM_BAND_EGSM, 0, 0, 0 }}, + { '2', 1, { MM_MODEM_BAND_DCS, 0, 0, 0 }}, + { '3', 1, { MM_MODEM_BAND_PCS, 0, 0, 0 }}, + { '4', 2, { MM_MODEM_BAND_G850, MM_MODEM_BAND_PCS, 0, 0 }}, + { '5', 2, { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, 0, 0 }}, + { '6', 2, { MM_MODEM_BAND_EGSM, MM_MODEM_BAND_PCS, 0, 0 }}, + { '7', 4, { MM_MODEM_BAND_DCS, MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_EGSM }} +}; + +/* Setup relationship between the 3G band bitmask in the modem and the bitmask + * in ModemManager. */ +typedef struct { + guint32 wavecom_band_flag; + MMModemBand mm_band; +} WavecomBand3G; +static const WavecomBand3G bands_3g[] = { + { (1 << 0), MM_MODEM_BAND_U2100 }, + { (1 << 1), MM_MODEM_BAND_U1900 }, + { (1 << 2), MM_MODEM_BAND_U1800 }, + { (1 << 3), MM_MODEM_BAND_U17IV }, + { (1 << 4), MM_MODEM_BAND_U850 }, + { (1 << 5), MM_MODEM_BAND_U800 }, + { (1 << 6), MM_MODEM_BAND_U2600 }, + { (1 << 7), MM_MODEM_BAND_U900 }, + { (1 << 8), MM_MODEM_BAND_U17IX } +}; + +/*****************************************************************************/ +/* Supported modes (Modem interface) */ + +static MMModemMode +load_supported_modes_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return MM_MODEM_MODE_NONE; + + return (MMModemMode) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (res))); +} + +static void +supported_ms_classes_query_ready (MMBaseModem *self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + const gchar *response; + GError *error = NULL; + MMModemMode mode; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (!response) { + /* Let the error be critical. */ + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + response = mm_strip_tag (response, "+CGCLASS:"); + mode = MM_MODEM_MODE_NONE; + + if (strstr (response, WAVECOM_MS_CLASS_A_IDSTR)) { + mm_dbg ("Modem supports Class A mobile station"); + mode |= MM_MODEM_MODE_3G; + } + + if (strstr (response, WAVECOM_MS_CLASS_B_IDSTR)) { + mm_dbg ("Modem supports Class B mobile station"); + mode |= (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS); + } + + if (strstr (response, WAVECOM_MS_CLASS_CG_IDSTR)) { + mm_dbg ("Modem supports Class CG mobile station"); + mode |= MM_MODEM_MODE_2G; + } + + if (strstr (response, WAVECOM_MS_CLASS_CC_IDSTR)) { + mm_dbg ("Modem supports Class CC mobile station"); + mode |= MM_MODEM_MODE_CS; + } + + /* If none received, error */ + if (mode == MM_MODEM_MODE_NONE) + g_simple_async_result_set_error (simple, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't get supported mobile station classes: '%s'", + response); + else + g_simple_async_result_set_op_res_gpointer (simple, + GUINT_TO_POINTER (mode), + NULL); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +load_supported_modes (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + load_supported_modes); + + mm_base_modem_at_command ( + MM_BASE_MODEM (self), + "+CGCLASS=?", + 3, + FALSE, + (GAsyncReadyCallback)supported_ms_classes_query_ready, + result); +} + +/*****************************************************************************/ +/* Load initial allowed/preferred modes (Modem interface) */ + +typedef struct { + MMModemMode allowed; + MMModemMode preferred; +} LoadAllowedModesResult; + +static gboolean +load_allowed_modes_finish (MMIfaceModem *self, + GAsyncResult *res, + MMModemMode *allowed, + MMModemMode *preferred, + GError **error) +{ + LoadAllowedModesResult *result; + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return FALSE; + + result = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); + + *allowed = result->allowed; + *preferred = result->preferred; + return TRUE; +} + +static void +wwsm_read_ready (MMBaseModem *self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + GRegex *r; + GMatchInfo *match_info = NULL; + LoadAllowedModesResult result; + const gchar *response; + GError *error = NULL; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (!response) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + result.allowed = MM_MODEM_MODE_NONE; + result.preferred = MM_MODEM_MODE_NONE; + + /* Possible responses: + * +WWSM: 0 (2G only) + * +WWSM: 1 (3G only) + * +WWSM: 2,0 (Any) + * +WWSM: 2,1 (2G preferred) + * +WWSM: 2,2 (3G preferred) + */ + r = g_regex_new ("\\r\\n\\+WWSM: ([0-2])(,([0-2]))?.*$", 0, 0, NULL); + g_assert (r != NULL); + + if (g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) { + guint allowed = 0; + + if (mm_get_uint_from_match_info (match_info, 1, &allowed)) { + switch (allowed) { + case 0: + result.allowed = MM_MODEM_MODE_2G; + result.preferred = MM_MODEM_MODE_NONE; + break; + case 1: + result.allowed = MM_MODEM_MODE_3G; + result.preferred = MM_MODEM_MODE_NONE; + break; + case 2: { + guint preferred = 0; + + result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); + + /* 3, to avoid the comma */ + if (mm_get_uint_from_match_info (match_info, 3, &preferred)) { + switch (preferred) { + case 0: + result.preferred = MM_MODEM_MODE_NONE; + break; + case 1: + result.preferred = MM_MODEM_MODE_2G; + break; + case 2: + result.preferred = MM_MODEM_MODE_3G; + break; + default: + g_warn_if_reached (); + break; + } + } + break; + } + default: + g_warn_if_reached (); + break; + } + } + } + + if (result.allowed == MM_MODEM_MODE_NONE) + g_simple_async_result_set_error (simple, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Unknown wireless data service reply: '%s'", + response); + else + g_simple_async_result_set_op_res_gpointer (simple, &result, NULL); + g_simple_async_result_complete (simple); + g_object_unref (simple); + + g_regex_unref (r); + if (match_info) + g_match_info_free (match_info); +} + +static void +current_ms_class_ready (MMBaseModem *self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + LoadAllowedModesResult result; + const gchar *response; + GError *error = NULL; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (!response) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + response = mm_strip_tag (response, "+CGCLASS:"); + + if (strncmp (response, + WAVECOM_MS_CLASS_A_IDSTR, + strlen (WAVECOM_MS_CLASS_A_IDSTR)) == 0) { + mm_dbg ("Modem configured as a Class A mobile station"); + /* For 3G devices, query WWSM status */ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+WWSM?", + 3, + FALSE, + (GAsyncReadyCallback)wwsm_read_ready, + simple); + return; + } + + result.allowed = MM_MODEM_MODE_NONE; + result.preferred = MM_MODEM_MODE_NONE; + + if (strncmp (response, + WAVECOM_MS_CLASS_B_IDSTR, + strlen (WAVECOM_MS_CLASS_B_IDSTR)) == 0) { + mm_dbg ("Modem configured as a Class B mobile station"); + result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS); + result.preferred = MM_MODEM_MODE_2G; + } else if (strncmp (response, + WAVECOM_MS_CLASS_CG_IDSTR, + strlen (WAVECOM_MS_CLASS_CG_IDSTR)) == 0) { + mm_dbg ("Modem configured as a Class CG mobile station"); + result.allowed = MM_MODEM_MODE_2G; + result.preferred = MM_MODEM_MODE_NONE; + } else if (strncmp (response, + WAVECOM_MS_CLASS_CC_IDSTR, + strlen (WAVECOM_MS_CLASS_CC_IDSTR)) == 0) { + mm_dbg ("Modem configured as a Class CC mobile station"); + result.allowed = MM_MODEM_MODE_CS; + result.preferred = MM_MODEM_MODE_NONE; + } + + if (result.allowed == MM_MODEM_MODE_NONE) + g_simple_async_result_set_error (simple, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Unknown mobile station class: '%s'", + response); + else + g_simple_async_result_set_op_res_gpointer (simple, &result, NULL); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +load_allowed_modes (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + load_allowed_modes); + + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CGCLASS?", + 3, + FALSE, + (GAsyncReadyCallback)current_ms_class_ready, + result); +} + +/*****************************************************************************/ +/* Set allowed modes (Modem interface) */ + +typedef struct { + MMBroadbandModemWavecom *self; + GSimpleAsyncResult *result; + MMModemMode allowed; + MMModemMode preferred; + gchar *cgclass_command; + gchar *wwsm_command; +} SetAllowedModesContext; + +static void +set_allowed_modes_context_complete_and_free (SetAllowedModesContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->result); + g_object_unref (ctx->self); + g_free (ctx->cgclass_command); + g_free (ctx->wwsm_command); + g_free (ctx); +} + +static gboolean +set_allowed_modes_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +wwsm_update_ready (MMBaseModem *self, + GAsyncResult *res, + SetAllowedModesContext *ctx) +{ + GError *error = NULL; + + mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (error) + /* Let the error be critical. */ + g_simple_async_result_take_error (ctx->result, error); + else + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + + set_allowed_modes_context_complete_and_free (ctx); +} + +static void +cgclass_update_ready (MMBaseModem *self, + GAsyncResult *res, + SetAllowedModesContext *ctx) +{ + GError *error = NULL; + + mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (error) { + /* Let the error be critical. */ + g_simple_async_result_take_error (ctx->result, error); + set_allowed_modes_context_complete_and_free (ctx); + return; + } + + if (!ctx->wwsm_command) { + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + set_allowed_modes_context_complete_and_free (ctx); + return; + } + + mm_base_modem_at_command (MM_BASE_MODEM (self), + ctx->wwsm_command, + 3, + FALSE, + (GAsyncReadyCallback)wwsm_update_ready, + ctx); +} + +static void +set_allowed_modes (MMIfaceModem *self, + MMModemMode allowed, + MMModemMode preferred, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SetAllowedModesContext *ctx; + + ctx = g_new (SetAllowedModesContext, 1); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + set_allowed_modes); + ctx->allowed = allowed; + ctx->preferred = preferred; + + if (allowed == MM_MODEM_MODE_CS) + ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_CC_IDSTR); + else if (allowed == MM_MODEM_MODE_2G) + ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_CG_IDSTR); + else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS) && + preferred == MM_MODEM_MODE_NONE) + ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_B_IDSTR); + else if (allowed & MM_MODEM_MODE_3G) { + if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G) || + allowed == (MM_MODEM_MODE_CS | MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { + if (preferred == MM_MODEM_MODE_2G) + ctx->wwsm_command = g_strdup ("+WWSM=2,1"); + else if (preferred == MM_MODEM_MODE_3G) + ctx->wwsm_command = g_strdup ("+WWSM=2,2"); + else if (preferred == MM_MODEM_MODE_NONE) + ctx->wwsm_command = g_strdup ("+WWSM=2,0"); + } else if (allowed == MM_MODEM_MODE_3G) + ctx->wwsm_command = g_strdup ("+WWSM=1"); + + if (ctx->wwsm_command) + ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_A_IDSTR); + } + + if (!ctx->cgclass_command) { + gchar *allowed_str; + gchar *preferred_str; + + allowed_str = mm_modem_mode_build_string_from_mask (allowed); + preferred_str = mm_modem_mode_build_string_from_mask (preferred); + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Requested mode (allowed: '%s', preferred: '%s') not " + "supported by the modem.", + allowed_str, + preferred_str); + g_free (allowed_str); + g_free (preferred_str); + + set_allowed_modes_context_complete_and_free (ctx); + return; + } + + mm_base_modem_at_command (MM_BASE_MODEM (self), + ctx->cgclass_command, + 3, + FALSE, + (GAsyncReadyCallback)cgclass_update_ready, + ctx); +} + +/*****************************************************************************/ +/* Load supported bands (Modem interface) */ + +static GArray * +load_supported_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + /* Never fails */ + return (GArray *) g_array_ref (g_simple_async_result_get_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (res))); +} + +static void +load_supported_bands (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + GArray *bands; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + load_supported_bands); + + /* We do assume that we already know if the modem is 2G-only, 3G-only or + * 2G+3G. This is checked quite before trying to load supported bands. */ + + /* Add 3G-specific bands */ + if (mm_iface_modem_is_3g (self)) { + bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 10); + g_array_index (bands, MMModemBand, 0) = MM_MODEM_BAND_U2100; + g_array_index (bands, MMModemBand, 1) = MM_MODEM_BAND_U1800; + g_array_index (bands, MMModemBand, 2) = MM_MODEM_BAND_U17IV; + g_array_index (bands, MMModemBand, 3) = MM_MODEM_BAND_U800; + g_array_index (bands, MMModemBand, 4) = MM_MODEM_BAND_U850; + g_array_index (bands, MMModemBand, 5) = MM_MODEM_BAND_U900; + g_array_index (bands, MMModemBand, 6) = MM_MODEM_BAND_U900; + g_array_index (bands, MMModemBand, 7) = MM_MODEM_BAND_U17IX; + g_array_index (bands, MMModemBand, 8) = MM_MODEM_BAND_U1900; + g_array_index (bands, MMModemBand, 9) = MM_MODEM_BAND_U2600; + } + /* Add 2G-specific bands */ + else { + bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); + g_array_index (bands, MMModemBand, 0) = MM_MODEM_BAND_EGSM; + g_array_index (bands, MMModemBand, 1) = MM_MODEM_BAND_DCS; + g_array_index (bands, MMModemBand, 2) = MM_MODEM_BAND_PCS; + g_array_index (bands, MMModemBand, 3) = MM_MODEM_BAND_G850; + } + + g_simple_async_result_set_op_res_gpointer (result, + bands, + (GDestroyNotify)g_array_unref); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +/*****************************************************************************/ +/* Load current bands (Modem interface) */ + +static GArray * +load_current_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return NULL; + + return (GArray *) g_array_ref (g_simple_async_result_get_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (res))); +} + +static void +get_2g_band_ready (MMBroadbandModemWavecom *self, + GAsyncResult *res, + GSimpleAsyncResult *operation_result) +{ + const gchar *response; + const gchar *p; + GError *error = NULL; + GArray *bands_array = NULL; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (!response) { + /* Let the error be critical. */ + g_simple_async_result_take_error (operation_result, error); + g_simple_async_result_complete (operation_result); + g_object_unref (operation_result); + return; + } + + p = mm_strip_tag (response, "+WMBS:"); + if (p) { + guint i; + + for (i = 0; i < G_N_ELEMENTS (bands_2g); i++) { + if (bands_2g[i].wavecom_band == *p) { + guint j; + + if (G_UNLIKELY (!bands_array)) + bands_array = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); + + for (j = 0; j < bands_2g[i].n_mm_bands; j++) + g_array_append_val (bands_array, bands_2g[i].mm_bands[j]); + } + } + } + + if (!bands_array) + g_simple_async_result_set_error (operation_result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't parse current bands reply: '%s'", + response); + else + g_simple_async_result_set_op_res_gpointer (operation_result, + bands_array, + (GDestroyNotify)g_array_unref); + + g_simple_async_result_complete (operation_result); + g_object_unref (operation_result); +} + +static void +get_3g_band_ready (MMBroadbandModemWavecom *self, + GAsyncResult *res, + GSimpleAsyncResult *operation_result) +{ + const gchar *response; + const gchar *p; + GError *error = NULL; + GArray *bands_array = NULL; + guint32 wavecom_band; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (!response) { + /* Let the error be critical. */ + g_simple_async_result_take_error (operation_result, error); + g_simple_async_result_complete (operation_result); + g_object_unref (operation_result); + return; + } + + /* Example reply: + * AT+WUBS? --> + * <-- +WUBS: "3",1 + * <-- OK + * The "3" meaning here Band I and II are selected. + */ + + p = mm_strip_tag (response, "+WUBS:"); + if (*p == '"') + p++; + + wavecom_band = atoi (p); + if (wavecom_band > 0) { + guint i; + + for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) { + if (bands_3g[i].wavecom_band_flag & wavecom_band) { + if (G_UNLIKELY (!bands_array)) + bands_array = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); + g_array_append_val (bands_array, bands_3g[i].mm_band); + } + } + } + + if (!bands_array) + g_simple_async_result_set_error (operation_result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't parse current bands reply: '%s'", + response); + else + g_simple_async_result_set_op_res_gpointer (operation_result, + bands_array, + (GDestroyNotify)g_array_unref); + + g_simple_async_result_complete (operation_result); + g_object_unref (operation_result); +} + +static void +load_current_bands (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + load_current_bands); + + if (mm_iface_modem_is_3g (self)) + mm_base_modem_at_command (MM_BASE_MODEM (self), + "AT+WUBS?", + 3, + FALSE, + (GAsyncReadyCallback)get_3g_band_ready, + result); + else + mm_base_modem_at_command (MM_BASE_MODEM (self), + "AT+WMBS?", + 3, + FALSE, + (GAsyncReadyCallback)get_2g_band_ready, + result); +} + +/*****************************************************************************/ +/* Set bands (Modem interface) */ + +static gboolean +set_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +wmbs_set_ready (MMBaseModem *self, + GAsyncResult *res, + GSimpleAsyncResult *operation_result) +{ + GError *error = NULL; + + if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) + /* Let the error be critical */ + g_simple_async_result_take_error (operation_result, error); + else + g_simple_async_result_set_op_res_gboolean (operation_result, TRUE); + + g_simple_async_result_complete (operation_result); + g_object_unref (operation_result); +} + +static void +set_bands_3g (MMIfaceModem *self, + GArray *bands_array, + GSimpleAsyncResult *result) +{ + GArray *bands_array_final; + guint wavecom_band = 0; + guint i; + gchar *bands_string; + gchar *cmd; + + /* The special case of ANY should be treated separately. */ + if (bands_array->len == 1 && + g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { + /* We build an array with all bands to set; so that we use the same + * logic to build the cinterion_band, and so that we can log the list of + * bands being set properly */ + bands_array_final = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), G_N_ELEMENTS (bands_3g)); + for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) + g_array_append_val (bands_array_final, bands_3g[i].mm_band); + } else + bands_array_final = g_array_ref (bands_array); + + for (i = 0; i < G_N_ELEMENTS (bands_3g); i++) { + guint j; + + for (j = 0; j < bands_array_final->len; j++) { + if (g_array_index (bands_array_final, MMModemBand, j) == bands_3g[i].mm_band) { + wavecom_band |= bands_3g[i].wavecom_band_flag; + break; + } + } + } + + bands_string = mm_common_build_bands_string ((MMModemBand *)bands_array_final->data, + bands_array_final->len); + g_array_unref (bands_array_final); + + if (wavecom_band == 0) { + g_simple_async_result_set_error (result, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "The given band combination is not supported: '%s'", + bands_string); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + g_free (bands_string); + return; + } + + mm_dbg ("Setting new bands to use: '%s'", bands_string); + cmd = g_strdup_printf ("+WMBS=\"%u\",1", wavecom_band); + mm_base_modem_at_command (MM_BASE_MODEM (self), + cmd, + 3, + FALSE, + (GAsyncReadyCallback)wmbs_set_ready, + result); + g_free (cmd); + g_free (bands_string); +} + +static void +set_bands_2g (MMIfaceModem *self, + GArray *bands_array, + GSimpleAsyncResult *result) +{ + GArray *bands_array_final; + gchar wavecom_band = '\0'; + guint i; + gchar *bands_string; + gchar *cmd; + + /* If the iface properly checked the given list against the supported bands, + * it's not possible to get an array longer than 4 here. */ + g_assert (bands_array->len <= 4); + + /* The special case of ANY should be treated separately. */ + if (bands_array->len == 1 && + g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { + const WavecomBand2G *all; + + /* All bands is the last element in our 2G bands array */ + all = &bands_2g[G_N_ELEMENTS (bands_2g) - 1]; + + /* We build an array with all bands to set; so that we use the same + * logic to build the cinterion_band, and so that we can log the list of + * bands being set properly */ + bands_array_final = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); + g_array_append_vals (bands_array_final, all->mm_bands, all->n_mm_bands); + } else + bands_array_final = g_array_ref (bands_array); + + for (i = 0; wavecom_band == '\0' && i < G_N_ELEMENTS (bands_2g); i++) { + GArray *supported_combination; + + supported_combination = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), bands_2g[i].n_mm_bands); + g_array_append_vals (supported_combination, bands_2g[i].mm_bands, bands_2g[i].n_mm_bands); + + /* Check if the given array is exactly one of the supported combinations */ + if (mm_common_bands_garray_cmp (bands_array_final, supported_combination)) + wavecom_band = bands_2g[i].wavecom_band; + + g_array_unref (supported_combination); + } + + bands_string = mm_common_build_bands_string ((MMModemBand *)bands_array_final->data, + bands_array_final->len); + g_array_unref (bands_array_final); + + if (wavecom_band == '\0') { + g_simple_async_result_set_error (result, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "The given band combination is not supported: '%s'", + bands_string); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + g_free (bands_string); + return; + } + + mm_dbg ("Setting new bands to use: '%s'", bands_string); + cmd = g_strdup_printf ("+WMBS=%c,1", wavecom_band); + mm_base_modem_at_command (MM_BASE_MODEM (self), + cmd, + 3, + FALSE, + (GAsyncReadyCallback)wmbs_set_ready, + result); + + g_free (cmd); + g_free (bands_string); +} + +static void +set_bands (MMIfaceModem *self, + GArray *bands_array, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + /* The bands that we get here are previously validated by the interface, and + * that means that ALL the bands given here were also given in the list of + * supported bands. BUT BUT, that doesn't mean that the exact list of bands + * will end up being valid, as not all combinations are possible. E.g, + * Wavecom modems supporting only 2G have specific combinations allowed. + */ + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + set_bands); + + if (mm_iface_modem_is_3g (self)) + set_bands_3g (self, bands_array, result); + else + set_bands_2g (self, bands_array, result); +} + +/*****************************************************************************/ +/* Load access technologies (Modem interface) */ + +static gboolean +load_access_technologies_finish (MMIfaceModem *self, + GAsyncResult *res, + MMModemAccessTechnology *access_technologies, + guint *mask, + GError **error) +{ + MMModemAccessTechnology act; + const gchar *p; + const gchar *response; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); + if (!response) + return FALSE; + + act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; + p = mm_strip_tag (response, "+WGPRSIND:"); + if (p) { + switch (*p) { + case '1': + /* GPRS only */ + act = MM_MODEM_ACCESS_TECHNOLOGY_GPRS; + break; + case '2': + /* EGPRS/EDGE supported */ + act = MM_MODEM_ACCESS_TECHNOLOGY_EDGE; + break; + case '3': + /* 3G R99 supported */ + act = MM_MODEM_ACCESS_TECHNOLOGY_UMTS; + break; + case '4': + /* HSDPA supported */ + act = MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; + break; + case '5': + /* HSUPA supported */ + act = MM_MODEM_ACCESS_TECHNOLOGY_HSUPA; + break; + default: + break; + } + } + + if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't parse access technologies result: '%s'", + response); + return FALSE; + } + + /* We are reporting ALL 3GPP access technologies here */ + *access_technologies = act; + *mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK; + return TRUE; +} + +static void +load_access_technologies (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+WGPRS=9,2", + 3, + FALSE, + callback, + user_data); +} + +/*****************************************************************************/ +/* Flow control (Modem interface) */ + +static gboolean +setup_flow_control_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); +} + +static void +setup_flow_control (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + /* Wavecom doesn't have XOFF/XON flow control, so we enable RTS/CTS */ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+IFC=2,2", + 3, + FALSE, + callback, + user_data); +} + +/*****************************************************************************/ +/* Modem power up (Modem interface) */ + +static gboolean +modem_power_up_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +full_functionality_status_ready (MMBaseModem *self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + GError *error = NULL; + + if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) + g_simple_async_result_take_error (simple, error); + else + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +get_current_functionality_status_ready (MMBaseModem *self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + const gchar *response; + GError *error = NULL; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (!response) { + mm_warn ("Failed checking if power-up command is needed: '%s'. " + "Will assume it isn't.", + error->message); + g_error_free (error); + /* On error, just assume we don't need the power-up command */ + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + response = mm_strip_tag (response, "+CFUN:"); + if (response && *response == '1') { + /* If reported functionality status is '1', then we do not need to + * issue the power-up command. Otherwise, do it. */ + mm_dbg ("Already in full functionality status, skipping power-up command"); + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + mm_warn ("Not in full functionality status, power-up command is needed. " + "Note that it may reboot the modem."); + + /* Try to go to full functionality mode without rebooting the system. + * Works well if we previously switched off the power with CFUN=4 + */ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CFUN=1,0", + 3, + FALSE, + (GAsyncReadyCallback)full_functionality_status_ready, + simple); +} + +static void +modem_power_up (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + modem_power_up); + + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CFUN?", + 3, + FALSE, + (GAsyncReadyCallback)get_current_functionality_status_ready, + result); +} + +/*****************************************************************************/ +/* Modem power down (Modem interface) */ + +static gboolean +modem_power_down_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); +} + +static void +modem_power_down (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and + * keeps access to the SIM */ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CFUN=4", + 3, + FALSE, + callback, + user_data); +} + +static void +setup_ports (MMBroadbandModem *self) +{ + gpointer parser; + MMAtSerialPort *primary; + GRegex *regex; + + /* Call parent's setup ports first always */ + MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_wavecom_parent_class)->setup_ports (self); + + /* Set 9600 baudrate by default in the AT port */ + mm_dbg ("Baudrate will be set to 9600 bps..."); + primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); + if (!primary) + return; + + /* AT+CPIN? replies will never have an OK appended */ + parser = mm_serial_parser_v1_new (); + regex = g_regex_new ("\\r\\n\\+CPIN: .*\\r\\n", + G_REGEX_RAW | G_REGEX_OPTIMIZE, + 0, NULL); + mm_serial_parser_v1_set_custom_regex (parser, regex, NULL); + g_regex_unref (regex); + + mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (primary), + mm_serial_parser_v1_parse, + parser, + mm_serial_parser_v1_destroy); +} + +/*****************************************************************************/ + +MMBroadbandModemWavecom * +mm_broadband_modem_wavecom_new (const gchar *device, + const gchar *driver, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id) +{ + return g_object_new (MM_TYPE_BROADBAND_MODEM_WAVECOM, + MM_BASE_MODEM_DEVICE, device, + MM_BASE_MODEM_DRIVER, driver, + MM_BASE_MODEM_PLUGIN, plugin, + MM_BASE_MODEM_VENDOR_ID, vendor_id, + MM_BASE_MODEM_PRODUCT_ID, product_id, + NULL); +} + +static void +mm_broadband_modem_wavecom_init (MMBroadbandModemWavecom *self) +{ +} + +static void +iface_modem_init (MMIfaceModem *iface) +{ + iface->load_supported_modes = load_supported_modes; + iface->load_supported_modes_finish = load_supported_modes_finish; + iface->load_allowed_modes = load_allowed_modes; + iface->load_allowed_modes_finish = load_allowed_modes_finish; + iface->set_allowed_modes = set_allowed_modes; + iface->set_allowed_modes_finish = set_allowed_modes_finish; + iface->load_supported_bands = load_supported_bands; + iface->load_supported_bands_finish = load_supported_bands_finish; + iface->load_current_bands = load_current_bands; + iface->load_current_bands_finish = load_current_bands_finish; + iface->set_bands = set_bands; + iface->set_bands_finish = set_bands_finish; + iface->load_access_technologies = load_access_technologies; + iface->load_access_technologies_finish = load_access_technologies_finish; + iface->setup_flow_control = setup_flow_control; + iface->setup_flow_control_finish = setup_flow_control_finish; + iface->modem_power_up = modem_power_up; + iface->modem_power_up_finish = modem_power_up_finish; + iface->modem_power_down = modem_power_down; + iface->modem_power_down_finish = modem_power_down_finish; +} + +static void +mm_broadband_modem_wavecom_class_init (MMBroadbandModemWavecomClass *klass) +{ + MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); + + broadband_modem_class->setup_ports = setup_ports; +}
diff --git a/plugins/wavecom/mm-broadband-modem-wavecom.h b/plugins/wavecom/mm-broadband-modem-wavecom.h new file mode 100644 index 0000000..3bec594 --- /dev/null +++ b/plugins/wavecom/mm-broadband-modem-wavecom.h
@@ -0,0 +1,50 @@ +/* -*- 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) 2011 Ammonit Measurement GmbH + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + * + * Author: Aleksander Morgado <aleksander@lanedo.com> + */ + +#ifndef MM_BROADBAND_MODEM_WAVECOM_H +#define MM_BROADBAND_MODEM_WAVECOM_H + +#include "mm-broadband-modem.h" + +#define MM_TYPE_BROADBAND_MODEM_WAVECOM (mm_broadband_modem_wavecom_get_type ()) +#define MM_BROADBAND_MODEM_WAVECOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_WAVECOM, MMBroadbandModemWavecom)) +#define MM_BROADBAND_MODEM_WAVECOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_WAVECOM, MMBroadbandModemWavecomClass)) +#define MM_IS_BROADBAND_MODEM_WAVECOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_WAVECOM)) +#define MM_IS_BROADBAND_MODEM_WAVECOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_WAVECOM)) +#define MM_BROADBAND_MODEM_WAVECOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_WAVECOM, MMBroadbandModemWavecomClass)) + +typedef struct _MMBroadbandModemWavecom MMBroadbandModemWavecom; +typedef struct _MMBroadbandModemWavecomClass MMBroadbandModemWavecomClass; + +struct _MMBroadbandModemWavecom { + MMBroadbandModem parent; +}; + +struct _MMBroadbandModemWavecomClass{ + MMBroadbandModemClass parent; +}; + +GType mm_broadband_modem_wavecom_get_type (void); + +MMBroadbandModemWavecom *mm_broadband_modem_wavecom_new (const gchar *device, + const gchar *driver, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id); + +#endif /* MM_BROADBAND_MODEM_WAVECOM_H */
diff --git a/plugins/wavecom/mm-plugin-wavecom.c b/plugins/wavecom/mm-plugin-wavecom.c new file mode 100644 index 0000000..d83f96e --- /dev/null +++ b/plugins/wavecom/mm-plugin-wavecom.c
@@ -0,0 +1,120 @@ +/* -*- 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. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Copyright (C) 2011 Ammonit Measurement GmbH + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + * + * Author: Aleksander Morgado <aleksander@lanedo.com> + */ + +#include <string.h> +#include <gmodule.h> + +#include <libmm-common.h> + +#include "mm-plugin-wavecom.h" +#include "mm-broadband-modem-wavecom.h" + +G_DEFINE_TYPE (MMPluginWavecom, mm_plugin_wavecom, MM_TYPE_PLUGIN_BASE) + +int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION; +int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION; + +/*****************************************************************************/ + +static MMBaseModem * +grab_port (MMPluginBase *base, + MMBaseModem *existing, + MMPortProbe *probe, + GError **error) +{ + MMBaseModem *modem = NULL; + const gchar *name, *subsys; + guint16 vendor = 0, product = 0; + + /* The Wavecom plugin cannot do anything with non-AT ports */ + if (!mm_port_probe_is_at (probe)) { + g_set_error_literal (error, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Ignoring non-AT port"); + return NULL; + } + + subsys = mm_port_probe_get_port_subsys (probe); + name = mm_port_probe_get_port_name (probe); + + if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) { + g_set_error_literal (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Could not get modem product ID"); + return NULL; + } + + /* If this is the first port being grabbed, create a new modem object */ + if (!existing) + modem = MM_BASE_MODEM (mm_broadband_modem_wavecom_new (mm_port_probe_get_port_physdev (probe), + mm_port_probe_get_port_driver (probe), + mm_plugin_get_name (MM_PLUGIN (base)), + vendor, + product)); + + if (!mm_base_modem_grab_port (existing ? existing : modem, + subsys, + name, + MM_PORT_TYPE_AT, /* we only allow AT ports here */ + MM_AT_PORT_FLAG_NONE, + error)) { + if (modem) + g_object_unref (modem); + return NULL; + } + + return existing ? existing : modem; +} + +/*****************************************************************************/ + +G_MODULE_EXPORT MMPlugin * +mm_plugin_create (void) +{ + static const gchar *subsystems[] = { "tty", NULL }; + static const guint16 vendor_ids[] = { 0x114f, 0 }; + + return MM_PLUGIN ( + g_object_new (MM_TYPE_PLUGIN_WAVECOM, + MM_PLUGIN_BASE_NAME, "Wavecom", + MM_PLUGIN_BASE_ALLOWED_SUBSYSTEMS, subsystems, + MM_PLUGIN_BASE_ALLOWED_VENDOR_IDS, vendor_ids, + MM_PLUGIN_BASE_ALLOWED_AT, TRUE, + NULL)); +} + +static void +mm_plugin_wavecom_init (MMPluginWavecom *self) +{ +} + +static void +mm_plugin_wavecom_class_init (MMPluginWavecomClass *klass) +{ + MMPluginBaseClass *pb_class = MM_PLUGIN_BASE_CLASS (klass); + + pb_class->grab_port = grab_port; +}
diff --git a/plugins/mm-plugin-wavecom.h b/plugins/wavecom/mm-plugin-wavecom.h similarity index 96% rename from plugins/mm-plugin-wavecom.h rename to plugins/wavecom/mm-plugin-wavecom.h index 5563a37..9b355d5 100644 --- a/plugins/mm-plugin-wavecom.h +++ b/plugins/wavecom/mm-plugin-wavecom.h
@@ -17,6 +17,8 @@ * Boston, MA 02111-1307, USA. * * Copyright (C) 2011 Ammonit Measurement GmbH + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + * * Author: Aleksander Morgado <aleksander@lanedo.com> */ @@ -24,7 +26,6 @@ #define MM_PLUGIN_WAVECOM_H #include "mm-plugin-base.h" -#include "mm-generic-gsm.h" #define MM_TYPE_PLUGIN_WAVECOM (mm_plugin_wavecom_get_type ()) #define MM_PLUGIN_WAVECOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_WAVECOM, MMPluginWavecom))
diff --git a/src/mm-bearer-list.c b/src/mm-bearer-list.c index 551279f..3c672f8 100644 --- a/src/mm-bearer-list.c +++ b/src/mm-bearer-list.c
@@ -170,7 +170,7 @@ GList *l; for (l = self->priv->bearers; l; l = g_list_next (l)) { - if (mm_bearer_cmp_properties (MM_BEARER (l->data), properties)) + if (mm_bearer_properties_cmp (mm_bearer_peek_config (MM_BEARER (l->data)), properties)) return g_object_ref (l->data); }
diff --git a/src/mm-bearer.c b/src/mm-bearer.c index c0b8c33..3cce948 100644 --- a/src/mm-bearer.c +++ b/src/mm-bearer.c
@@ -45,6 +45,7 @@ PROP_CONNECTION, PROP_MODEM, PROP_STATUS, + PROP_CONFIG, PROP_LAST }; @@ -59,6 +60,8 @@ gchar *path; /* Status of this bearer */ MMBearerStatus status; + /* Configuration of the bearer */ + MMBearerProperties *config; /* Cancellable for connect() */ GCancellable *connect_cancellable; @@ -68,28 +71,12 @@ /*****************************************************************************/ -static void -bearer_expose_properties (MMBearer *self) -{ - MMBearerProperties *properties; - GVariant *dictionary; - - properties = MM_BEARER_GET_CLASS (self)->expose_properties (self); - dictionary = mm_bearer_properties_get_dictionary (properties); - mm_gdbus_bearer_set_properties (MM_GDBUS_BEARER (self), dictionary); - g_variant_unref (dictionary); - g_object_unref (properties); -} - void mm_bearer_export (MMBearer *self) { static guint id = 0; gchar *path; - /* Expose properties before exporting */ - bearer_expose_properties (self); - path = g_strdup_printf (MM_DBUS_BEARER_PREFIX "/%d", id++); g_object_set (self, MM_BEARER_PATH, path, @@ -625,6 +612,20 @@ return self->priv->path; } +MMBearerProperties * +mm_bearer_peek_config (MMBearer *self) +{ + return self->priv->config; +} + +MMBearerProperties * +mm_bearer_get_config (MMBearer *self) +{ + return (self->priv->config ? + g_object_ref (self->priv->config) : + NULL); +} + /*****************************************************************************/ static void @@ -685,17 +686,6 @@ return MM_BEARER_GET_CLASS (self)->report_disconnection (self); } -/*****************************************************************************/ - -gboolean -mm_bearer_cmp_properties (MMBearer *self, - MMBearerProperties *properties) -{ - return MM_BEARER_GET_CLASS (self)->cmp_properties (self, properties); -} - -/*****************************************************************************/ - static void set_property (GObject *object, guint prop_id, @@ -738,6 +728,18 @@ /* We don't allow g_object_set()-ing the status property */ g_assert_not_reached (); break; + case PROP_CONFIG: { + GVariant *dictionary; + + g_clear_object (&self->priv->config); + self->priv->config = g_value_dup_object (value); + /* Also expose the properties */ + dictionary = mm_bearer_properties_get_dictionary (self->priv->config); + mm_gdbus_bearer_set_properties (MM_GDBUS_BEARER (self), dictionary); + if (dictionary) + g_variant_unref (dictionary); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -765,6 +767,9 @@ case PROP_STATUS: g_value_set_enum (value, self->priv->status); break; + case PROP_CONFIG: + g_value_set_object (value, self->priv->config); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -812,8 +817,8 @@ g_clear_object (&self->priv->connection); } - if (self->priv->modem) - g_clear_object (&self->priv->modem); + g_clear_object (&self->priv->modem); + g_clear_object (&self->priv->config); G_OBJECT_CLASS (mm_bearer_parent_class)->dispose (object); } @@ -865,4 +870,12 @@ MM_BEARER_STATUS_DISCONNECTED, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_STATUS, properties[PROP_STATUS]); + + properties[PROP_CONFIG] = + g_param_spec_object (MM_BEARER_CONFIG, + "Bearer configuration", + "List of user provided properties", + MM_TYPE_BEARER_PROPERTIES, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_CONFIG, properties[PROP_CONFIG]); }
diff --git a/src/mm-bearer.h b/src/mm-bearer.h index 6f35e2d..1791b35 100644 --- a/src/mm-bearer.h +++ b/src/mm-bearer.h
@@ -40,6 +40,7 @@ #define MM_BEARER_CONNECTION "bearer-connection" #define MM_BEARER_MODEM "bearer-modem" #define MM_BEARER_STATUS "bearer-status" +#define MM_BEARER_CONFIG "bearer-config" typedef enum { /*< underscore_name=mm_bearer_status >*/ MM_BEARER_STATUS_DISCONNECTED, @@ -78,25 +79,17 @@ /* Report disconnection */ void (* report_disconnection) (MMBearer *bearer); - - /* Check if the bearer has the exact same properties */ - gboolean (* cmp_properties) (MMBearer *self, - MMBearerProperties *properties); - - /* Builder of the properties to be exposed in DBus. Bearers should expose only - * the input properties they actually ended up using */ - MMBearerProperties * (* expose_properties) (MMBearer *self); }; GType mm_bearer_get_type (void); void mm_bearer_export (MMBearer *self); -const gchar *mm_bearer_get_path (MMBearer *bearer); -void mm_bearer_expose_properties (MMBearer *bearer, - MMBearerProperties *properties); +const gchar *mm_bearer_get_path (MMBearer *bearer); +MMBearerStatus mm_bearer_get_status (MMBearer *bearer); +MMBearerProperties *mm_bearer_peek_config (MMBearer *self); +MMBearerProperties *mm_bearer_get_config (MMBearer *self); -MMBearerStatus mm_bearer_get_status (MMBearer *bearer); void mm_bearer_connect (MMBearer *self, GAsyncReadyCallback callback, @@ -116,7 +109,4 @@ void mm_bearer_report_disconnection (MMBearer *self); -gboolean mm_bearer_cmp_properties (MMBearer *self, - MMBearerProperties *properties); - #endif /* MM_BEARER_H */
diff --git a/src/mm-broadband-bearer.c b/src/mm-broadband-bearer.c index a90360b..cf55c7b 100644 --- a/src/mm-broadband-bearer.c +++ b/src/mm-broadband-bearer.c
@@ -53,24 +53,8 @@ CONNECTION_TYPE_CDMA, } ConnectionType; -enum { - PROP_0, - PROP_3GPP_APN, - PROP_CDMA_NUMBER, - PROP_CDMA_RM_PROTOCOL, - PROP_IP_TYPE, - PROP_ALLOW_ROAMING, - PROP_LAST -}; - -static GParamSpec *properties[PROP_LAST]; - struct _MMBroadbandBearerPrivate { /*-- Common stuff --*/ - /* IP type */ - gchar *ip_type; - /* Flag to allow/forbid connections while roaming */ - gboolean allow_roaming; /* Data port used when modem is connected */ MMPort *port; /* Current connection type */ @@ -81,8 +65,6 @@ ConnectionForbiddenReason reason_3gpp; /* Handler ID for the registration state change signals */ guint id_3gpp_registration_change; - /* APN of the PDP context */ - gchar *apn; /* CID of the PDP context */ guint cid; @@ -92,10 +74,6 @@ /* Handler IDs for the registration state change signals */ guint id_cdma1x_registration_change; guint id_evdo_registration_change; - /* (Optional) Number to dial */ - gchar *number; - /* Protocol of the Rm interface */ - MMModemCdmaRmProtocol rm_protocol; }; /*****************************************************************************/ @@ -107,38 +85,6 @@ }; /*****************************************************************************/ - -const gchar * -mm_broadband_bearer_get_3gpp_apn (MMBroadbandBearer *self) -{ - return self->priv->apn; -} - -MMModemCdmaRmProtocol -mm_broadband_bearer_get_cdma_rm_protocol (MMBroadbandBearer *self) -{ - return self->priv->rm_protocol; -} - -const gchar * -mm_broadband_bearer_get_ip_type (MMBroadbandBearer *self) -{ - return self->priv->ip_type; -} - -gboolean -mm_broadband_bearer_get_allow_roaming (MMBroadbandBearer *self) -{ - return self->priv->allow_roaming; -} - -guint -mm_broadband_bearer_get_3gpp_cid (MMBroadbandBearer *self) -{ - return self->priv->cid; -} - -/*****************************************************************************/ /* Detailed connect result, used in both CDMA and 3GPP sequences */ typedef struct { MMBearerIpConfig *ipv4_config; @@ -328,12 +274,15 @@ cdma_connect_context_dial (DetailedConnectContext *ctx) { gchar *command; + const gchar *number; + + number = mm_bearer_properties_get_number (mm_bearer_peek_config (MM_BEARER (ctx->self))); /* If a number was given when creating the bearer, use that one. * Otherwise, use the default one, #777 */ - if (ctx->self->priv->number) - command = g_strconcat ("DT", ctx->self->priv->number, NULL); + if (number) + command = g_strconcat ("DT", number, NULL); else command = g_strdup ("DT#777"); @@ -405,14 +354,14 @@ return; } - if (current_rm != ctx->self->priv->rm_protocol) { + if (current_rm != mm_bearer_properties_get_rm_protocol (mm_bearer_peek_config (MM_BEARER (self)))) { guint new_index; gchar *command; mm_dbg ("Setting requested RM protocol..."); new_index = (mm_cdma_get_index_from_rm_protocol ( - ctx->self->priv->rm_protocol, + mm_bearer_properties_get_rm_protocol (mm_bearer_peek_config (MM_BEARER (self))), &error)); if (error) { mm_warn ("Cannot set RM protocol: '%s'", @@ -462,7 +411,9 @@ callback, user_data); - if (self->priv->rm_protocol != MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN) { + if (mm_bearer_properties_get_rm_protocol ( + mm_bearer_peek_config (MM_BEARER (self))) != + MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN) { /* Need to query current RM protocol */ mm_dbg ("Querying current RM protocol set..."); mm_base_modem_at_command_full (ctx->modem, @@ -754,7 +705,7 @@ } static void -initialize_pdp_context_ready (MMBaseModem *self, +initialize_pdp_context_ready (MMBaseModem *modem, GAsyncResult *res, DetailedConnectContext *ctx) { @@ -764,7 +715,7 @@ if (detailed_connect_context_complete_and_free_if_cancelled (ctx)) return; - mm_base_modem_at_command_full_finish (self, res, &error); + mm_base_modem_at_command_full_finish (modem, res, &error); if (error) { mm_warn ("Couldn't initialize PDP context with our APN: '%s'", error->message); @@ -783,7 +734,7 @@ } static void -find_cid_ready (MMBaseModem *self, +find_cid_ready (MMBaseModem *modem, GAsyncResult *res, DetailedConnectContext *ctx) { @@ -791,7 +742,7 @@ gchar *command; GError *error = NULL; - result = mm_base_modem_at_sequence_full_finish (self, res, NULL, &error); + result = mm_base_modem_at_sequence_full_finish (modem, res, NULL, &error); if (!result) { mm_warn ("Couldn't find best CID to use: '%s'", error->message); g_simple_async_result_take_error (ctx->result, error); @@ -807,9 +758,10 @@ /* Initialize PDP context with our APN */ ctx->cid = g_variant_get_uint32 (result); - command = g_strdup_printf ("+CGDCONT=%u,\"IP\",\"%s\"", + command = g_strdup_printf ("+CGDCONT=%u,\"%s\",\"%s\"", ctx->cid, - ctx->self->priv->apn); + mm_bearer_properties_get_ip_type (mm_bearer_peek_config (MM_BEARER (ctx->self))), + mm_bearer_properties_get_apn (mm_bearer_peek_config (MM_BEARER (ctx->self)))); mm_base_modem_at_command_full (ctx->modem, ctx->primary, command, @@ -822,7 +774,7 @@ } static gboolean -parse_cid_range (MMBaseModem *self, +parse_cid_range (MMBaseModem *modem, DetailedConnectContext *ctx, const gchar *command, const gchar *response, @@ -867,8 +819,7 @@ pdp_type = g_match_info_fetch (match_info, 3); - /* TODO: What about PDP contexts of type "IPV6"? */ - if (g_str_equal (pdp_type, "IP")) { + if (g_str_equal (pdp_type, mm_bearer_properties_get_ip_type (mm_bearer_peek_config (MM_BEARER (ctx->self))))) { gchar *max_cid_range_str; guint max_cid_range; @@ -907,7 +858,7 @@ } static gboolean -parse_pdp_list (MMBaseModem *self, +parse_pdp_list (MMBaseModem *modem, DetailedConnectContext *ctx, const gchar *command, const gchar *response, @@ -954,20 +905,25 @@ pdp->cid, pdp->pdp_type ? pdp->pdp_type : "", pdp->apn ? pdp->apn : ""); - if (g_str_equal (pdp->pdp_type, "IP")) { + if (g_str_equal (pdp->pdp_type, mm_bearer_properties_get_ip_type (mm_bearer_peek_config (MM_BEARER (ctx->self))))) { /* PDP with no APN set? we may use that one if not exact match found */ if (!pdp->apn || !pdp->apn[0]) { mm_dbg ("Found PDP context with CID %u and no APN", pdp->cid); cid = pdp->cid; - } else if (ctx->self->priv->apn && - g_str_equal (pdp->apn, ctx->self->priv->apn)) { - /* Found a PDP context with the same CID, we'll use it. */ - mm_dbg ("Found PDP context with CID %u for APN '%s'", - pdp->cid, pdp->apn); - cid = pdp->cid; - /* In this case, stop searching */ - break; + } else { + const gchar *apn; + + apn = mm_bearer_properties_get_apn (mm_bearer_peek_config (MM_BEARER (ctx->self))); + if (apn && + g_str_equal (pdp->apn, apn)) { + /* Found a PDP context with the same CID and PDP type, we'll use it. */ + mm_dbg ("Found PDP context with CID %u and PDP type %s for APN '%s'", + pdp->cid, pdp->pdp_type, pdp->apn); + cid = pdp->cid; + /* In this case, stop searching */ + break; + } } } @@ -1767,41 +1723,6 @@ /*****************************************************************************/ -static gboolean -cmp_properties (MMBearer *self, - MMBearerProperties *properties) -{ - MMBroadbandBearer *broadband = MM_BROADBAND_BEARER (self); - - return ((!g_strcmp0 (broadband->priv->apn, - mm_bearer_properties_get_apn (properties))) && - (!g_strcmp0 (broadband->priv->ip_type, - mm_bearer_properties_get_ip_type (properties))) && - (broadband->priv->allow_roaming == - mm_bearer_properties_get_allow_roaming (properties)) && - (!g_strcmp0 (broadband->priv->number, - mm_bearer_properties_get_number (properties))) && - (broadband->priv->rm_protocol == - mm_bearer_properties_get_rm_protocol (properties))); -} - -static MMBearerProperties * -expose_properties (MMBearer *self) -{ - MMBroadbandBearer *broadband = MM_BROADBAND_BEARER (self); - MMBearerProperties *properties; - - properties = mm_bearer_properties_new (); - mm_bearer_properties_set_apn (properties, broadband->priv->apn); - mm_bearer_properties_set_number (properties, broadband->priv->number); - mm_bearer_properties_set_rm_protocol (properties, broadband->priv->rm_protocol); - mm_bearer_properties_set_ip_type (properties, broadband->priv->ip_type); - mm_bearer_properties_set_allow_roaming (properties, broadband->priv->allow_roaming); - return properties; -} - -/*****************************************************************************/ - typedef struct _InitAsyncContext InitAsyncContext; static void interface_initialization_step (InitAsyncContext *ctx); @@ -1885,9 +1806,12 @@ if (mm_cdma_parse_crm_test_response (response, &min, &max, &error)) { + MMModemCdmaRmProtocol current; + + current = mm_bearer_properties_get_rm_protocol (mm_bearer_peek_config (MM_BEARER (ctx->self))); /* Check if value within the range */ - if (ctx->self->priv->rm_protocol >= min && - ctx->self->priv->rm_protocol <= max) { + if (current >= min && + current <= max) { /* Fine, go on with next step */ ctx->step++; interface_initialization_step (ctx); @@ -1897,8 +1821,7 @@ error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Requested RM protocol '%s' is not supported", - mm_modem_cdma_rm_protocol_get_string ( - ctx->self->priv->rm_protocol)); + mm_modem_cdma_rm_protocol_get_string (current)); } /* Failed, set as fatal as well */ @@ -1933,7 +1856,7 @@ self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_NONE; break; case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING: - if (self->priv->allow_roaming) { + if (mm_bearer_properties_get_allow_roaming (mm_bearer_peek_config (MM_BEARER (self)))) { mm_dbg ("Bearer allowed to connect, registered in roaming network"); self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_NONE; } else { @@ -1964,7 +1887,7 @@ if (cdma1x_state == MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING || evdo_state == MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING) { - if (self->priv->allow_roaming) { + if (mm_bearer_properties_get_allow_roaming (mm_bearer_peek_config (MM_BEARER (self)))) { mm_dbg ("Bearer allowed to connect, registered in roaming network"); self->priv->reason_cdma = CONNECTION_FORBIDDEN_REASON_NONE; } else { @@ -1998,7 +1921,8 @@ /* If a specific RM protocol is given, we need to check whether it is * supported. */ if (mm_iface_modem_is_cdma (MM_IFACE_MODEM (ctx->modem)) && - ctx->self->priv->rm_protocol != MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN) { + mm_bearer_properties_get_rm_protocol ( + mm_bearer_peek_config (MM_BEARER (ctx->self))) != MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN) { mm_base_modem_at_command_full (ctx->modem, ctx->port, "+CRM=?", @@ -2106,79 +2030,12 @@ cancellable, callback, user_data, - MM_BEARER_MODEM, modem, - MM_BROADBAND_BEARER_3GPP_APN, mm_bearer_properties_get_apn (properties), - MM_BROADBAND_BEARER_CDMA_NUMBER, mm_bearer_properties_get_number (properties), - MM_BROADBAND_BEARER_CDMA_RM_PROTOCOL, mm_bearer_properties_get_rm_protocol (properties), - MM_BROADBAND_BEARER_IP_TYPE, mm_bearer_properties_get_ip_type (properties), - MM_BROADBAND_BEARER_ALLOW_ROAMING, mm_bearer_properties_get_allow_roaming (properties), + MM_BEARER_MODEM, modem, + MM_BEARER_CONFIG, properties, NULL); } static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearer *self = MM_BROADBAND_BEARER (object); - - switch (prop_id) { - case PROP_3GPP_APN: - g_free (self->priv->apn); - self->priv->apn = g_value_dup_string (value); - break; - case PROP_CDMA_NUMBER: - g_free (self->priv->number); - self->priv->number = g_value_dup_string (value); - break; - case PROP_CDMA_RM_PROTOCOL: - self->priv->rm_protocol = g_value_get_enum (value); - break; - case PROP_IP_TYPE: - g_free (self->priv->ip_type); - self->priv->ip_type = g_value_dup_string (value); - break; - case PROP_ALLOW_ROAMING: - self->priv->allow_roaming = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MMBroadbandBearer *self = MM_BROADBAND_BEARER (object); - - switch (prop_id) { - case PROP_3GPP_APN: - g_value_set_string (value, self->priv->apn); - break; - case PROP_CDMA_NUMBER: - g_value_set_string (value, self->priv->number); - break; - case PROP_CDMA_RM_PROTOCOL: - g_value_set_enum (value, self->priv->rm_protocol); - break; - case PROP_IP_TYPE: - g_value_set_string (value, self->priv->ip_type); - break; - case PROP_ALLOW_ROAMING: - g_value_set_boolean (value, self->priv->allow_roaming); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void mm_broadband_bearer_init (MMBroadbandBearer *self) { /* Initialize private data */ @@ -2188,8 +2045,6 @@ /* Set defaults */ self->priv->connection_type = CONNECTION_TYPE_NONE; - self->priv->allow_roaming = TRUE; - self->priv->rm_protocol = MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN; self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_NONE; self->priv->reason_cdma = CONNECTION_FORBIDDEN_REASON_NONE; } @@ -2225,17 +2080,6 @@ } static void -finalize (GObject *object) -{ - MMBroadbandBearer *self = MM_BROADBAND_BEARER (object); - - g_free (self->priv->apn); - g_free (self->priv->ip_type); - - G_OBJECT_CLASS (mm_broadband_bearer_parent_class)->finalize (object); -} - -static void async_initable_iface_init (GAsyncInitableIface *iface) { iface->init_async = initable_init_async; @@ -2251,13 +2095,8 @@ g_type_class_add_private (object_class, sizeof (MMBroadbandBearerPrivate)); /* Virtual methods */ - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; object_class->dispose = dispose; - bearer_class->cmp_properties = cmp_properties; - bearer_class->expose_properties = expose_properties; bearer_class->connect = connect; bearer_class->connect_finish = connect_finish; bearer_class->disconnect = disconnect; @@ -2276,45 +2115,4 @@ klass->disconnect_3gpp_finish = detailed_disconnect_finish; klass->disconnect_cdma = disconnect_cdma; klass->disconnect_cdma_finish = detailed_disconnect_finish; - - properties[PROP_3GPP_APN] = - g_param_spec_string (MM_BROADBAND_BEARER_3GPP_APN, - "3GPP APN", - "Access Point Name to use in the connection", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_3GPP_APN, properties[PROP_3GPP_APN]); - - properties[PROP_CDMA_NUMBER] = - g_param_spec_string (MM_BROADBAND_BEARER_CDMA_NUMBER, - "Number to dial", - "Number to dial when launching the CDMA connection", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_CDMA_NUMBER, properties[PROP_CDMA_NUMBER]); - - properties[PROP_CDMA_RM_PROTOCOL] = - g_param_spec_enum (MM_BROADBAND_BEARER_CDMA_RM_PROTOCOL, - "Rm Protocol", - "Protocol to use in the CDMA Rm interface", - MM_TYPE_MODEM_CDMA_RM_PROTOCOL, - MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_CDMA_RM_PROTOCOL, properties[PROP_CDMA_RM_PROTOCOL]); - - properties[PROP_IP_TYPE] = - g_param_spec_string (MM_BROADBAND_BEARER_IP_TYPE, - "IP type", - "IP setup to use in the connection", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_IP_TYPE, properties[PROP_IP_TYPE]); - - properties[PROP_ALLOW_ROAMING] = - g_param_spec_boolean (MM_BROADBAND_BEARER_ALLOW_ROAMING, - "Allow roaming", - "Whether connections are allowed when roaming", - TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_ALLOW_ROAMING, properties[PROP_ALLOW_ROAMING]); }
diff --git a/src/mm-broadband-bearer.h b/src/mm-broadband-bearer.h index 5911a61..00478f2 100644 --- a/src/mm-broadband-bearer.h +++ b/src/mm-broadband-bearer.h
@@ -146,11 +146,6 @@ MMBearer *mm_broadband_bearer_new_finish (GAsyncResult *res, GError **error); -const gchar *mm_broadband_bearer_get_3gpp_apn (MMBroadbandBearer *self); -guint mm_broadband_bearer_get_cdma_rm_protocol (MMBroadbandBearer *self); -const gchar *mm_broadband_bearer_get_ip_type (MMBroadbandBearer *self); -gboolean mm_broadband_bearer_get_allow_roaming (MMBroadbandBearer *self); - guint mm_broadband_bearer_get_3gpp_cid (MMBroadbandBearer *self); #endif /* MM_BROADBAND_BEARER_H */
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 60a9be9..9a787ca 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c
@@ -340,6 +340,7 @@ static const ModemCaps modem_caps[] = { { "+CGSM", MM_MODEM_CAPABILITY_GSM_UMTS }, { "+CLTE2", MM_MODEM_CAPABILITY_LTE }, /* Novatel */ + { "+CLTE1", MM_MODEM_CAPABILITY_LTE }, /* Novatel */ { "+CLTE", MM_MODEM_CAPABILITY_LTE }, { "+CIS707-A", MM_MODEM_CAPABILITY_CDMA_EVDO }, { "+CIS707A", MM_MODEM_CAPABILITY_CDMA_EVDO }, /* Cmotech */
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index a99eac3..6019dfe 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c
@@ -1332,7 +1332,7 @@ /*************************************************************************/ MMModemAccessTechnology -mm_3gpp_string_to_access_tech (const gchar *string) +mm_string_to_access_tech (const gchar *string) { MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; @@ -1367,6 +1367,15 @@ if (strcasestr (string, "GSM")) act |= MM_MODEM_ACCESS_TECHNOLOGY_GSM; + if (strcasestr (string, "EvDO Rel0")) + act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDO0; + + if (strcasestr (string, "EvDO RelA")) + act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDOA; + + if (strcasestr (string, "1xRTT")) + act |= MM_MODEM_ACCESS_TECHNOLOGY_1XRTT; + return act; }
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index 10ec800..8da0a17 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h
@@ -147,7 +147,7 @@ MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str); gchar *mm_3gpp_facility_to_acronym (MMModem3gppFacility facility); -MMModemAccessTechnology mm_3gpp_string_to_access_tech (const gchar *string); +MMModemAccessTechnology mm_string_to_access_tech (const gchar *string); gchar *mm_3gpp_parse_operator (const gchar *reply, MMModemCharset cur_charset);
diff --git a/src/mm-sms.c b/src/mm-sms.c index 849722f..b68ee76 100644 --- a/src/mm-sms.c +++ b/src/mm-sms.c
@@ -1292,7 +1292,7 @@ "Is multipart", "Flag specifying if the SMS is multipart", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_IS_MULTIPART, properties[PROP_IS_MULTIPART]); properties[PROP_MAX_PARTS] = @@ -1300,7 +1300,7 @@ "Max parts", "Maximum number of parts composing this SMS", 1,255, 1, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_MAX_PARTS, properties[PROP_MAX_PARTS]); properties[PROP_MULTIPART_REFERENCE] = @@ -1308,6 +1308,6 @@ "Multipart reference", "Common reference for all parts in the multipart SMS", 0, G_MAXUINT, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_MULTIPART_REFERENCE, properties[PROP_MULTIPART_REFERENCE]); }
diff --git a/src/tests/test-sms-part.c b/src/tests/test-sms-part.c index d3bf7d5..8ed02d5 100644 --- a/src/tests/test-sms-part.c +++ b/src/tests/test-sms-part.c
@@ -45,6 +45,7 @@ const gchar *expected_smsc, const gchar *expected_number, const gchar *expected_timestamp, + gboolean expected_multipart, const gchar *expected_text, const guint8 *expected_data, gsize expected_data_size, @@ -65,6 +66,7 @@ g_assert_cmpstr (expected_timestamp, ==, mm_sms_part_get_timestamp (part)); if (expected_text) g_assert_cmpstr (expected_text, ==, mm_sms_part_get_text (part)); + g_assert_cmpuint (expected_multipart, ==, mm_sms_part_should_concat (part)); if (expected_data) { guint32 i; @@ -87,6 +89,7 @@ const gchar *expected_smsc, const gchar *expected_number, const gchar *expected_timestamp, + gboolean expected_multipart, const gchar *expected_text, const guint8 *expected_data, gsize expected_data_size, @@ -99,6 +102,7 @@ expected_smsc, expected_number, expected_timestamp, + expected_multipart, expected_text, expected_data, expected_data_size, @@ -133,6 +137,7 @@ "+12404492164", /* smsc */ "+16175927198", /* number */ "110228115050-05", /* timestamp */ + FALSE, "Here's a longer message [{with some extended characters}] " "thrown in, such as £ and ΩΠΨ and §¿ as well.", /* text */ NULL, 0, 0); @@ -153,6 +158,7 @@ "+79037011111", /* smsc */ "InternetSMS", /* number */ "110329192004+04", /* timestamp */ + FALSE, "ัะตัั", /* text */ NULL, 0, 0); } @@ -172,6 +178,7 @@ "+12345678901", /* smsc */ "+18005551212", /* number */ "110101123456+00", /* timestamp */ + FALSE, "hellohello", /* text */ NULL, 0, 0); } @@ -192,6 +199,7 @@ "+12345678901", /* smsc */ "+18005551212", /* number */ "110101123456+00", /* timestamp */ + FALSE, "hellohello", /* text */ NULL, 0, 0); } @@ -212,6 +220,7 @@ "+12345678901", /* smsc */ "+18005551212", /* number */ "110101123456+00", /* timestamp */ + FALSE, "hellohello", /* text */ NULL, 0, 0); } @@ -232,6 +241,7 @@ "+12345678901", /* smsc */ "18005551212", /* number, no plus */ "110101123456+00", /* timestamp */ + FALSE, "hellohello", /* text */ NULL, 0, 0); } @@ -253,6 +263,7 @@ "+12345678901", /* smsc */ "+18005551212", /* number */ "110101123456+00", /* timestamp */ + FALSE, "", /* text */ expected_data, /* data */ sizeof (expected_data), /* data size */ @@ -301,6 +312,7 @@ "+33609001390", /* smsc */ "1800", /* number */ "110624130815+02", /* timestamp */ + FALSE, "Info SFR - Confidentiel, à ne jamais transmettre -\r\n" "Voici votre nouveau mot de passe : sw2ced pour gérer " "votre compte SFR sur www.sfr.fr ou par téléphone au 963", /* text */ @@ -324,6 +336,7 @@ "+12345678901", /* smsc */ "+18005551212", /* number */ "110101123456+00", /* timestamp */ + FALSE, "", /* text */ expected_data, /* data */ sizeof (expected_data), /* data size */ @@ -369,12 +382,46 @@ "+31653131316", /* smsc */ "1002", /* number */ "110629233219+02", /* timestamp */ + TRUE, "Welkom, bel om uw Voicemail te beluisteren naar +31612001233" " (PrePay: *100*1233#). Voicemail ontvangen is altijd gratis." " Voor gebruik van mobiel interne", /* text */ NULL, 0, 0); } +static void +test_pdu_multipart (void) +{ + static const gchar *hexpdu1 = + "07912160130320F5440B916171056429F5000021405291650569A00500034C0201A9E8F41C949E" + "83C2207B599E07B1DFEE33885E9ED341E4F23C7D7697C920FA1B54C697E5E3F4BC0C6AD7D9F434" + "081E96D341E3303C2C4EB3D3F4BC0B94A483E6E8779D4D06CDD1EF3BA80E0785E7A0B7BB0C6A97" + "E7F3F0B9CC02B9DF7450780EA2DFDF2C50780EA2A3CBA0BA9B5C96B3F369F71954768FDFE4B4FB" + "0C9297E1F2F2BCECA6CF41"; + static const gchar *hexpdu2 = + "07912160130320F6440B916171056429F5000021405291651569320500034C0202E9E8301D4447" + "9741F0B09C3E0785E56590BCCC0ED3CB6410FD0D7ABBCBA0B0FB4D4797E52E10"; + + common_test_part_from_hexpdu ( + hexpdu1, + "+12063130025", /* smsc */ + "+16175046925", /* number */ + "120425195650-04", /* timestamp */ + TRUE, /* multipart! */ + "This is a very long test designed to exercise multi part capability. It should " + "show up as one message, not as two, as the underlying encoding represents ", /* text */ + NULL, 0, 0); + + common_test_part_from_hexpdu ( + hexpdu2, + "+12063130026", /* smsc */ + "+16175046925", /* number */ + "120425195651-04", /* timestamp */ + TRUE, /* multipart! */ + "that the parts are related to one another. ", /* text */ + NULL, 0, 0); +} + /********************* SMS ADDRESS ENCODER TESTS *********************/ static void @@ -637,6 +684,7 @@ g_test_add_func ("/MM/SMS/PDU-Parser/pdu-dcsf-8bit", test_pdu_dcsf_8bit); g_test_add_func ("/MM/SMS/PDU-Parser/pdu-insufficient-data", test_pdu_insufficient_data); g_test_add_func ("/MM/SMS/PDU-Parser/pdu-udhi", test_pdu_udhi); + g_test_add_func ("/MM/SMS/PDU-Parser/pdu-multipart", test_pdu_multipart); g_test_add_func ("/MM/SMS/Address-Encoder/smsc-intl", test_address_encode_smsc_intl); g_test_add_func ("/MM/SMS/Address-Encoder/smsc-unknown", test_address_encode_smsc_unknown);