aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-06-29 07:29:57 -0400
committerDan Williams <dcbw@redhat.com>2009-06-29 07:29:57 -0400
commit504b4991cd3aecd358d92a9c39233e6ca09036fa (patch)
tree88dfe78a241166ae963712b04cc3bdac8ae720cf
parent6077763d90b69cfc60b23f383c4529f966facaaf (diff)
parentef0a604dc2fb6c6fe3e9231a8ee85890c6ef6e85 (diff)
Merge commit 'origin/master' into udev
-rw-r--r--plugins/mm-modem-mbm.c795
-rw-r--r--plugins/mm-modem-mbm.h46
-rw-r--r--plugins/mm-plugin-mbm.c42
-rw-r--r--plugins/mm-plugin-mbm.h40
4 files changed, 609 insertions, 314 deletions
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index e0f03455..04ee5d92 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -1,53 +1,93 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
- Additions to NetworkManager, network-manager-applet and modemmanager
- for supporting Ericsson modules like F3507g.
+ * Copyright (C) 2008 Ericsson AB
+ *
+ * Author: Per Hallsmark <per.hallsmark@ericsson.com>
+ * Bjorn Runaker <bjorn.runaker@ericsson.com>
+ * Torgny Johansson <torgny.johansson@ericsson.com>
+ * Jonas Sjöquist <jonas.sjoquist@ericsson.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
- Copyright (C) 2008 Ericsson MBM
-
- Author: Per Hallsmark <per@hallsmark.se>
- Bjorn Runaker <bjorn.runaker@ericsson.com>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <stdio.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
-#include <errno.h>
#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <dbus/dbus-glib.h>
#include "mm-modem-mbm.h"
-#include "mm-serial.h"
-#include "mm-serial-parsers.h"
+#include "mm-modem-simple.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
-static gpointer mm_modem_mbm_parent_class = NULL;
-
#define MM_MODEM_MBM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_MBM, MMModemMbmPrivate))
+#define MBM_E2NAP_DISCONNECTED 0
+#define MBM_E2NAP_CONNECTED 1
+#define MBM_E2NAP_CONNECTING 2
+
+#define MBM_SIGNAL_INDICATOR 2
+#define MBM_SEND_DELAY 1000
+
+#define MBM_NETWORK_MODE_ANY 1
+#define MBM_NETWORK_MODE_2G 5
+#define MBM_NETWORK_MODE_3G 6
+
+#define MBM_ERINFO_2G_GPRS 1
+#define MBM_ERINFO_2G_EGPRS 2
+#define MBM_ERINFO_3G_UMTS 1
+#define MBM_ERINFO_3G_HSDPA 2
+
+static gpointer mm_modem_mbm_parent_class = NULL;
+
typedef struct {
- guint32 signal_quality;
+ guint reg_id;
+ gboolean have_emrdy;
+ char *network_device;
+ MMCallbackInfo *do_connect_done_info;
+ int account_index;
+ int network_mode;
+ const char *username;
+ const char *password;
} MMModemMbmPrivate;
+enum {
+ PROP_0,
+ PROP_NETWORK_DEVICE,
+
+ LAST_PROP
+};
+
+static void
+mbm_modem_authenticate (MMModemMbm *self,
+ const char *username,
+ const char *password,
+ gpointer user_data);
+
+static void
+mbm_set_network_mode_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data);
+
+static const char *
+mbm_simple_get_string_property (GHashTable *properties, const char *name, GError **error);
+
+static uint
+mbm_simple_get_uint_property (GHashTable *properties, const char *name, GError **error);
+
MMModem *
mm_modem_mbm_new (const char *serial_device,
const char *network_device,
@@ -59,7 +99,7 @@ mm_modem_mbm_new (const char *serial_device,
return MM_MODEM (g_object_new (MM_TYPE_MODEM_MBM,
MM_SERIAL_DEVICE, serial_device,
- MM_SERIAL_SEND_DELAY, (guint64) 10000,
+ MM_SERIAL_SEND_DELAY, (guint64) MBM_SEND_DELAY,
MM_MODEM_DRIVER, driver,
MM_MODEM_DEVICE, network_device,
MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_DHCP,
@@ -67,108 +107,217 @@ mm_modem_mbm_new (const char *serial_device,
NULL));
}
+/*****************************************************************************/
+/* Gsm network class override functions */
+/*****************************************************************************/
+
+typedef struct {
+ MMModemGsmNetwork *modem;
+ const char *network_id;
+ MMModemFn callback;
+ gpointer user_data;
+} RegisterData;
+
+static gboolean
+register_done (gpointer user_data)
+{
+ RegisterData *reg_data = user_data;
+ MMModemMbm *self = MM_MODEM_MBM (reg_data->modem);
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self);
+ MMModemGsmNetwork *parent_modem_iface;
+
+ priv->reg_id = 0;
+
+ mm_serial_queue_command (MM_SERIAL (reg_data->modem), "+CREG=1", 3, NULL, NULL);
+ mm_serial_queue_command (MM_SERIAL (reg_data->modem), "+CMER=3,0,0,1", 3, NULL, NULL);
+
+ parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GSM_NETWORK_GET_INTERFACE (reg_data->modem));
+ parent_modem_iface->do_register (MM_MODEM_GSM_NETWORK (reg_data->modem),
+ reg_data->network_id,
+ reg_data->callback,
+ reg_data->user_data);
+ return FALSE;
+}
+
static void
-eiapsw_done (MMSerial *serial,
- GString *response,
- GError *error,
+do_register (MMModemGsmNetwork *modem,
+ const char *network_id,
+ MMModemFn callback,
gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemMbm *self = MM_MODEM_MBM (modem);
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self);
+ MMCallbackInfo *info;
+ RegisterData *reg_data;
- if (error)
- info->error = g_error_copy (error);
+ info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
- mm_callback_info_schedule (info);
+ reg_data = g_malloc0 (sizeof(RegisterData));
+ reg_data->modem = modem;
+ reg_data->network_id = network_id;
+ reg_data->callback = callback;
+ reg_data->user_data = user_data;
+
+ /* wait so sim pin is done */
+ if (priv->reg_id)
+ g_source_remove (priv->reg_id);
+ priv->reg_id = g_timeout_add_full (G_PRIORITY_DEFAULT, 500,
+ register_done, reg_data,
+ g_free);
}
static void
-eiac_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+mbm_cind_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *command;
+ char *cind;
+ int quality = 0, batt;
if (error)
info->error = g_error_copy (error);
+ else {
+ cind = strstr (response->str, "+CIND:");
+ if (cind) {
+ if (sscanf (cind, " %d,%d", &batt, &quality) == 2)
+ quality *= 20; /* normalize to percent */
+ }
- command = g_strdup_printf ("AT*EIAPSW=1,1,\"%s\"",
- (char *) mm_callback_info_get_data (info, "apn"));
-
- mm_serial_queue_command (serial, command, 10, eiapsw_done, info);
- g_free (command);
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
+ }
+ mm_callback_info_schedule (info);
}
static void
-eiad_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+get_signal_quality (MMModemGsmNetwork *modem,
+ MMModemUIntFn callback,
+ gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMCallbackInfo *info;
- if (error)
- info->error = g_error_copy (error);
+ info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+ mm_serial_queue_command (MM_SERIAL (modem), "+CIND?", 3, mbm_cind_done, info);
+}
- mm_serial_queue_command (serial, "AT*EIAC=1", 10, eiac_done, info);
+static int
+mbm_parse_network_mode (int network_mode)
+{
+ switch (network_mode) {
+ case MM_MODEM_GSM_NETWORK_MODE_ANY:
+ case MM_MODEM_GSM_NETWORK_MODE_3G_PREFERRED:
+ case MM_MODEM_GSM_NETWORK_MODE_2G_PREFERRED:
+ return MBM_NETWORK_MODE_ANY;
+ case MM_MODEM_GSM_NETWORK_MODE_GPRS:
+ case MM_MODEM_GSM_NETWORK_MODE_EDGE:
+ case MM_MODEM_GSM_NETWORK_MODE_2G_ONLY:
+ return MBM_NETWORK_MODE_2G;
+ case MM_MODEM_GSM_NETWORK_MODE_3G_ONLY:
+ case MM_MODEM_GSM_NETWORK_MODE_HSDPA:
+ return MBM_NETWORK_MODE_3G;
+ default:
+ return MBM_NETWORK_MODE_ANY;
+ }
}
static void
-set_apn (MMModemGsmNetwork *modem,
- const char *apn,
- MMModemFn callback,
- gpointer user_data)
+set_network_mode (MMModemGsmNetwork *modem,
+ MMModemGsmNetworkMode mode,
+ MMModemFn callback,
+ gpointer user_data)
{
MMCallbackInfo *info;
+ char *command;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
- mm_callback_info_set_data (info, "apn", g_strdup (apn), g_free);
- mm_serial_queue_command (MM_SERIAL (modem), "AT*EIAD=0", 10, eiad_done, info);
+ command = g_strdup_printf ("+CFUN=%d", mbm_parse_network_mode (mode));
+ mm_serial_queue_command (MM_SERIAL (modem), command, 3, mbm_set_network_mode_done, info);
+ g_free (command);
}
static void
-do_cmer_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+mbm_get_network_mode_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ char *erinfo;
+ int mode = 0, gsm = 0, umts = 0;
+ gboolean parsed = FALSE;
- if (error)
+ if (error) {
info->error = g_error_copy (error);
+ goto done;
+ }
+
+ erinfo = strstr (response->str, "*ERINFO:");
+ if (!erinfo)
+ goto done;
+
+ if (sscanf (erinfo + 8, "%d,%d,%d", &mode, &gsm, &umts) != 3)
+ goto done;
+
+ if (gsm || umts) {
+ MMModemGsmNetworkMode mm_mode = MM_MODEM_GSM_NETWORK_MODE_ANY;
+
+ if (gsm == MBM_ERINFO_2G_GPRS)
+ mm_mode = MM_MODEM_GSM_NETWORK_MODE_GPRS;
+ else if (gsm == MBM_ERINFO_2G_EGPRS)
+ mm_mode = MM_MODEM_GSM_NETWORK_MODE_EDGE;
+ else if (umts == MBM_ERINFO_3G_UMTS)
+ mm_mode = MM_MODEM_GSM_NETWORK_MODE_UMTS;
+ else if (umts == MBM_ERINFO_3G_HSDPA)
+ mm_mode = MM_MODEM_GSM_NETWORK_MODE_HSDPA;
+ else
+ g_debug ("%s unknown network mode %d,%d", __FUNCTION__, gsm, umts);
+
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_mode), NULL);
+ parsed = TRUE;
+ }
+
+done:
+ if (!error && !parsed) {
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse network mode results");
+ }
mm_callback_info_schedule (info);
}
static void
-do_register_done (MMSerial *serial,
- GString *response,
- GError *error,
+get_network_mode (MMModemGsmNetwork *modem,
+ MMModemUIntFn callback,
gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- if (error)
- info->error = g_error_copy (error);
+ MMCallbackInfo *info;
- mm_serial_queue_command (serial, "AT+CMER=3,0,0,1", 10, do_cmer_done, info);
+ info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+ mm_serial_queue_command (MM_SERIAL (modem), "*ERINFO?", 3, mbm_get_network_mode_done, info);
}
+/*****************************************************************************/
+/* Simple Modem class override functions */
+/*****************************************************************************/
+
static void
-do_register (MMModemGsmNetwork *modem,
- const char *network_id,
- MMModemFn callback,
- gpointer user_data)
+simple_connect (MMModemSimple *simple,
+ GHashTable *properties,
+ MMModemFn callback,
+ gpointer user_data)
{
- MMCallbackInfo *info;
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (simple);
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemSimple *parent_iface;
+ uint network_mode = 0;
- info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
+ priv->username = mbm_simple_get_string_property (properties, "username", &info->error);
+ priv->password = mbm_simple_get_string_property (properties, "password", &info->error);
- sleep (4);
+ network_mode = mbm_simple_get_uint_property (properties, "network_mode", &info->error);
+ priv->network_mode = mbm_parse_network_mode (network_mode);
- mm_serial_queue_command (MM_SERIAL (modem), "AT*ENAP=1,1", 10, do_register_done, info);
+ parent_iface = g_type_interface_peek_parent (MM_MODEM_SIMPLE_GET_INTERFACE (simple));
+ parent_iface->connect (MM_MODEM_SIMPLE (simple), properties, callback, info);
}
/*****************************************************************************/
@@ -176,38 +325,66 @@ do_register (MMModemGsmNetwork *modem,
/*****************************************************************************/
static void
-enable_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+mbm_enable_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
if (error)
info->error = g_error_copy (error);
-
mm_callback_info_schedule (info);
}
static void
-init_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+mbm_init_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (serial);
+ char *command;
if (error) {
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
+ } else {
+ if (!priv->network_mode)
+ priv->network_mode = MBM_NETWORK_MODE_ANY;
+ command = g_strdup_printf ("+CFUN=%d", priv->network_mode);
+ mm_serial_queue_command (serial, command, 3, mbm_enable_done, info);
+ g_free (command);
+ }
+}
+
+static void
+do_init (MMSerial *serial, gpointer user_data)
+{
+ mm_serial_queue_command (serial, "&F E0 V1 X4 &C1 +CMEE=1", 3, mbm_init_done, user_data);
+}
+
+static void
+mbm_emrdy_done (MMSerial *serial, GString *response, GError *error, gpointer user_data)
+{
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (serial);
+
+ if ( error
+ && error->domain == MM_SERIAL_ERROR
+ && error->code == MM_SERIAL_RESPONSE_TIMEOUT) {
+ g_warning ("%s: timed out waiting for EMRDY response.", __func__);
} else
- mm_serial_queue_command (serial, "+CFUN=1", 5, enable_done, user_data);
+ priv->have_emrdy = TRUE;
+
+ do_init (serial, user_data);
}
static void
enable_flash_done (MMSerial *serial, gpointer user_data)
{
- mm_serial_queue_command (serial, "&F E0 +CMEE=1", 3, init_done, user_data);
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (serial);
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (priv->have_emrdy) {
+ /* Modem is ready, no need to check EMRDY */
+ do_init (serial, info);
+ } else
+ mm_serial_queue_command (serial, "*EMRDY?", 5, mbm_emrdy_done, info);
}
static void
@@ -216,17 +393,19 @@ disable_done (MMSerial *serial,
GError *error,
gpointer user_data)
{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
mm_serial_close (serial);
- mm_callback_info_schedule ((MMCallbackInfo *) user_data);
+ mm_callback_info_schedule (info);
}
static void
-disable_flash_done (MMSerial *serial, gpointer user_data)
+disable_flash_done (MMSerial *serial,
+ gpointer user_data)
{
- mm_serial_queue_command (serial, "+CFUN=4", 5, disable_done, user_data);
+ mm_serial_queue_command (serial, "+CMER=0", 5, disable_done, user_data);
}
-
static void
enable (MMModem *modem,
gboolean do_enable,
@@ -235,221 +414,286 @@ enable (MMModem *modem,
{
MMCallbackInfo *info;
- /* First, reset the previously used CID */
mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0);
info = mm_callback_info_new (modem, callback, user_data);
- if (!do_enable) {
- if (mm_serial_is_connected (MM_SERIAL (modem)))
- mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info);
- else
- disable_flash_done (MM_SERIAL (modem), info);
- } else {
+ if (do_enable) {
if (mm_serial_open (MM_SERIAL (modem), &info->error))
mm_serial_flash (MM_SERIAL (modem), 100, enable_flash_done, info);
if (info->error)
mm_callback_info_schedule (info);
+ } else {
+ mm_serial_queue_command (MM_SERIAL (modem), "+CREG=0", 100, NULL, NULL);
+ mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem));
+ if (mm_serial_is_connected (MM_SERIAL (modem)))
+ mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info);
+ else
+ disable_flash_done (MM_SERIAL (modem), info);
}
-
}
-static gboolean
-parse_erinfo (const char *reply, int *mode, int *gsm_rinfo, int *umts_rinfo)
+static void
+do_connect (MMModem *modem,
+ const char *number,
+ MMModemFn callback,
+ gpointer user_data)
{
- g_return_val_if_fail (reply != NULL, FALSE);
- g_return_val_if_fail (mode != NULL, FALSE);
- g_return_val_if_fail (gsm_rinfo != NULL, FALSE);
- g_return_val_if_fail (umts_rinfo != NULL, FALSE);
+ MMCallbackInfo *info;
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (modem);
- if (strncmp (reply, "*ERINFO:", 8))
- return FALSE;
+ info = mm_callback_info_new (modem, callback, user_data);
+ priv->do_connect_done_info = info;
- if (sscanf (reply + 8, "%d,%d,%d", mode, gsm_rinfo, umts_rinfo))
- return TRUE;
+ mbm_modem_authenticate (MM_MODEM_MBM (modem), priv->username, priv->password, info);
+}
- return FALSE;
+static void
+disconnect (MMModem *modem,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new (modem, callback, user_data);
+ mm_serial_queue_command (MM_SERIAL (modem), "AT*ENAP=0", 3, NULL, info);
+
+ mm_callback_info_schedule (info);
}
+/*****************************************************************************/
+
static void
-get_network_mode_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+mbm_set_network_mode_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
if (error)
info->error = g_error_copy (error);
- else {
- int mode = 0, gsm_rinfo = 0, umts_rinfo = 0;
- guint32 result = 0;
-
- if (parse_erinfo (response->str, &mode, &gsm_rinfo, &umts_rinfo)) {
- if (umts_rinfo == 2)
- result = MM_MODEM_GSM_NETWORK_MODE_HSDPA;
- else if (umts_rinfo && !gsm_rinfo)
- result = MM_MODEM_GSM_NETWORK_MODE_UMTS;
- else if (umts_rinfo && gsm_rinfo)
- result = MM_MODEM_GSM_NETWORK_MODE_3G_PREFERRED;
- else if (gsm_rinfo) {
- switch (gsm_rinfo) {
- case 2:
- case 3:
- result = MM_MODEM_GSM_NETWORK_MODE_EDGE;
- break;
- case 1:
- default:
- result = MM_MODEM_GSM_NETWORK_MODE_GPRS;
- break;
- }
- }
- }
-
- if (result == 0)
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Could not parse network mode results");
- else
- mm_callback_info_set_result (info, GUINT_TO_POINTER (result), NULL);
- }
mm_callback_info_schedule (info);
}
static void
-get_network_mode (MMModemGsmNetwork *modem,
- MMModemUIntFn callback,
- gpointer user_data)
+mbm_emrdy_received (MMSerial *serial,
+ GMatchInfo *info,
+ gpointer user_data)
{
- MMCallbackInfo *info;
-
- info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "AT*ERINFO?", 3, get_network_mode_done, info);
+ MM_MODEM_MBM_GET_PRIVATE (serial)->have_emrdy = TRUE;
}
-/* GetSignalQuality */
-
static void
-get_signal_quality_done (MMSerial *serial,
- GString *response,
- GError *error,
- gpointer user_data)
+mbm_pacsp0_received (MMSerial *serial,
+ GMatchInfo *info,
+ gpointer user_data)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *reply = response->str;
+ return;
+}
- if (error)
- info->error = g_error_copy (error);
- else if (!strncmp (reply, "+CIND: ", 7)) {
- /* Got valid reply */
- int battch;
- int quality;
-
- reply += 7;
-
- if (sscanf (reply, "%d,%d", &battch, &quality)) {
- /* Normalize the quality */
- quality = quality * 100 / 5;
-
- MM_MODEM_MBM_GET_PRIVATE (serial)->signal_quality = quality;
- mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
- } else
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Could not parse signal quality results");
+static void
+mbm_ciev_received (MMSerial *serial,
+ GMatchInfo *info,
+ gpointer user_data)
+{
+ int quality = 0, ind = 0;
+ const char *str;
+
+ str = g_match_info_fetch (info, 1);
+ if (str)
+ ind = atoi (str);
+
+ if (ind == MBM_SIGNAL_INDICATOR) {
+ str = g_match_info_fetch (info, 2);
+ if (str) {
+ quality = atoi (str);
+ mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK(serial), quality * 20);
+ }
}
+}
- mm_callback_info_schedule (info);
+static void
+mbm_do_connect_done (MMModemMbm *self)
+{
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self);
+
+ mm_callback_info_schedule (priv->do_connect_done_info);
}
static void
-get_signal_quality (MMModemGsmNetwork *modem,
- MMModemUIntFn callback,
+mbm_e2nap_received (MMSerial *serial,
+ GMatchInfo *info,
gpointer user_data)
{
- MMCallbackInfo *info;
-
- if (mm_serial_is_connected (MM_SERIAL (modem))) {
- g_message ("Returning saved signal quality %d", MM_MODEM_MBM_GET_PRIVATE (modem)->signal_quality);
- callback (MM_MODEM (modem), MM_MODEM_MBM_GET_PRIVATE (modem)->signal_quality, NULL, user_data);
- return;
+ int state = 0;
+ const char *str;
+
+ str = g_match_info_fetch (info, 1);
+ if (str)
+ state = atoi (str);
+
+ if (MBM_E2NAP_DISCONNECTED == state)
+ g_debug ("%s, disconnected", __func__);
+ else if (MBM_E2NAP_CONNECTED == state) {
+ g_debug ("%s, connected", __func__);
+ mbm_do_connect_done (MM_MODEM_MBM (serial));
+ } else if (MBM_E2NAP_CONNECTING == state)
+ g_debug("%s, connecting", __func__);
+ else {
+ /* Should not happen */
+ g_debug("%s, undefined e2nap status",__FUNCTION__);
+ g_assert_not_reached ();
}
-
- info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
- mm_serial_queue_command (MM_SERIAL (modem), "+CIND?", 3, get_signal_quality_done, info);
}
-/*****************************************************************************/
+static void
+e2nap_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ char *command;
+
+ if (error) {
+ info->error = g_error_copy (error);
+ /* TODO: Fallback to polling of enap status */
+ mm_callback_info_schedule (info);
+ } else {
+ guint32 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (serial));
+ command = g_strdup_printf ("AT*ENAP=1,%d",cid);
+ mm_serial_queue_command (serial, command, 3, NULL, NULL);
+ g_free (command);
+ }
+}
static void
-boot_trig (MMSerial *serial,
- GMatchInfo *match_info,
- gpointer user_data)
+mbm_auth_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- mm_serial_queue_command (serial, "AT*ENAP=1,1", 10, NULL, NULL);
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (error) {
+ info->error = g_error_copy (error);
+ mm_callback_info_schedule (info);
+ } else
+ mm_serial_queue_command (MM_SERIAL (serial), "AT*E2NAP=1", 3, e2nap_done, user_data);
}
static void
-ciev_trig (MMSerial *serial,
- GMatchInfo *match_info,
- gpointer user_data)
+mbm_modem_authenticate (MMModemMbm *self,
+ const char *username,
+ const char *password,
+ gpointer user_data)
{
- char *str;
- int event, value;
- guint32 quality;
+ if (username || password) {
+ char *command;
- str = g_match_info_fetch (match_info, 1);
- event = str[0] - '0';
- g_free (str);
+ command = g_strdup_printf ("*EIAAUW=%d,1,\"%s\",\"%s\"",
+ mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)),
+ username ? username : "",
+ password ? password : "");
- str = g_match_info_fetch (match_info, 2);
- value = str[0] - '0';
- g_free (str);
+ mm_serial_queue_command (MM_SERIAL (self), command, 3, mbm_auth_done, user_data);
+ g_free (command);
+ } else
+ mbm_auth_done (MM_SERIAL (self), NULL, NULL, user_data);
+}
- switch (event) {
- case 2: /* signal quality, value 0-5 */
- quality = value * 100 / 5;
- mm_modem_gsm_network_signal_quality (MM_MODEM_GSM_NETWORK (serial), quality);
- break;
- case 9: /* roaming, value 0 or 1 */
- g_debug ("%s: roaming %s\n", __FUNCTION__, value ? "active" : "inactive");
- break;
- default:
- g_debug ("%s: got unknown event %d with value %d\n", __FUNCTION__, event, value);
- }
+static const char *
+mbm_simple_get_string_property (GHashTable *properties, const char *name, GError **error)
+{
+ GValue *value;
+
+ value = (GValue *) g_hash_table_lookup (properties, name);
+ if (!value)
+ return NULL;
+
+ if (G_VALUE_HOLDS_STRING (value))
+ return g_value_get_string (value);
+
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Invalid property type for '%s': %s (string expected)",
+ name, G_VALUE_TYPE_NAME (value));
+
+ return NULL;
}
-static void
-mm_modem_mbm_init (MMModemMbm *self)
+static uint
+mbm_simple_get_uint_property (GHashTable *properties, const char *name, GError **error)
{
- GRegex *regex;
+ GValue *value;
+
+ value = (GValue *) g_hash_table_lookup (properties, name);
+ if (!value)
+ return 0;
+
+ if (G_VALUE_HOLDS_UINT (value))
+ return g_value_get_uint (value);
+
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Invalid property type for '%s': %s (uint expected)",
+ name, G_VALUE_TYPE_NAME (value));
+
+ return 0;
+}
- regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, boot_trig, NULL, NULL);
- g_regex_unref (regex);
+/*****************************************************************************/
- regex = g_regex_new ("\\r\\n[\\*]EMWI\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, NULL, NULL, NULL);
- g_regex_unref (regex);
+static void
+modem_gsm_network_init (MMModemGsmNetwork *class)
+{
+ class->do_register = do_register;
+ class->get_signal_quality = get_signal_quality;
+ class->get_network_mode = get_network_mode;
+ class->set_network_mode = set_network_mode;
+}
- regex = g_regex_new ("\\r\\n\\+CIEV: (\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, ciev_trig, NULL, NULL);
- g_regex_unref (regex);
+static void
+modem_simple_init (MMModemSimple *class)
+{
+ class->connect = simple_connect;
}
static void
modem_init (MMModem *modem_class)
{
modem_class->enable = enable;
+ modem_class->connect = do_connect;
+ modem_class->disconnect = disconnect;
}
static void
-modem_gsm_network_init (MMModemGsmNetwork *class)
+mm_modem_mbm_init (MMModemMbm *self)
{
- class->do_register = do_register;
- class->set_apn = set_apn;
- class->get_network_mode = get_network_mode;
- class->get_signal_quality = get_signal_quality;
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self);
+ GRegex *emrdy_regex, *e2nap_regex, *pacsp0_regex, *ciev_regex;
+
+ priv->have_emrdy = FALSE;
+
+ mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (self), TRUE);
+
+ emrdy_regex = g_regex_new ("\\r\\n\\*EMRDY: \\d\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), emrdy_regex, mbm_emrdy_received, self, NULL);
+
+ e2nap_regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), e2nap_regex, mbm_e2nap_received, self, NULL);
+
+ pacsp0_regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), pacsp0_regex, mbm_pacsp0_received, self, NULL);
+
+ ciev_regex = g_regex_new ("\\r\\n\\+CIEV: (\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), ciev_regex, mbm_ciev_received, self, NULL);
+
+ g_regex_unref (emrdy_regex);
+ g_regex_unref (e2nap_regex);
+ g_regex_unref (pacsp0_regex);
+ g_regex_unref (ciev_regex);
}
static GObject*
@@ -457,9 +701,9 @@ constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
+ MMModemMbmPrivate *priv;
GObject *object;
- char *modem_device;
- char *serial_device;
+ char *modem_device, *serial_device;
object = G_OBJECT_CLASS (mm_modem_mbm_parent_class)->constructor (type,
n_construct_params,
@@ -467,6 +711,8 @@ constructor (GType type,
if (!object)
return NULL;
+ priv = MM_MODEM_MBM_GET_PRIVATE (object);
+
/* Make sure both serial device and data device are provided */
g_object_get (object,
MM_MODEM_DEVICE, &modem_device,
@@ -486,6 +732,49 @@ constructor (GType type,
}
static void
+finalize (GObject *object)
+{
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (object);
+
+ if (priv->reg_id)
+ g_source_remove (priv->reg_id);
+
+ g_free (priv->network_device);
+
+ G_OBJECT_CLASS (mm_modem_mbm_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_NETWORK_DEVICE:
+ /* Construct only */
+ priv->network_device = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ switch (prop_id) {
+ case PROP_NETWORK_DEVICE:
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
mm_modem_mbm_class_init (MMModemMbmClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -495,6 +784,9 @@ mm_modem_mbm_class_init (MMModemMbmClass *klass)
/* Virtual methods */
object_class->constructor = constructor;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
}
GType
@@ -519,6 +811,10 @@ mm_modem_mbm_get_type (void)
(GInterfaceInitFunc) modem_init
};
+ static const GInterfaceInfo modem_simple_info = {
+ (GInterfaceInitFunc) modem_simple_init
+ };
+
static const GInterfaceInfo modem_gsm_network_info = {
(GInterfaceInitFunc) modem_gsm_network_init
};
@@ -526,6 +822,7 @@ mm_modem_mbm_get_type (void)
modem_mbm_type = g_type_register_static (MM_TYPE_GENERIC_GSM, "MMModemMbm", &modem_mbm_type_info, 0);
g_type_add_interface_static (modem_mbm_type, MM_TYPE_MODEM, &modem_iface_info);
+ g_type_add_interface_static (modem_mbm_type, MM_TYPE_MODEM_SIMPLE, &modem_simple_info);
g_type_add_interface_static (modem_mbm_type, MM_TYPE_MODEM_GSM_NETWORK, &modem_gsm_network_info);
}
diff --git a/plugins/mm-modem-mbm.h b/plugins/mm-modem-mbm.h
index 9a26f1a3..aff0bcc4 100644
--- a/plugins/mm-modem-mbm.h
+++ b/plugins/mm-modem-mbm.h
@@ -1,27 +1,27 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
- Additions to NetworkManager, network-manager-applet and modemmanager
- for supporting Ericsson modules like F3507g.
-
- Author: Per Hallsmark <per@hallsmark.se>
- Bjorn Runaker <bjorn.runaker@ericsson.com>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Copyright (C) 2008 Ericsson AB
+ *
+ * Author: Per Hallsmark <per.hallsmark@ericsson.com>
+ * Bjorn Runaker <bjorn.runaker@ericsson.com>
+ * Torgny Johansson <torgny.johansson@ericsson.com>
+ * Jonas Sjöquist <jonas.sjoquist@ericsson.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
#ifndef MM_MODEM_MBM_H
#define MM_MODEM_MBM_H
@@ -35,6 +35,8 @@
#define MM_IS_MODEM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_MBM))
#define MM_MODEM_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_MBM, MMModemMbmClass))
+#define MM_MODEM_MBM_NETWORK_DEVICE "network-device"
+
typedef struct {
MMGenericGsm parent;
} MMModemMbm;
diff --git a/plugins/mm-plugin-mbm.c b/plugins/mm-plugin-mbm.c
index 0018ec9d..c4b58e55 100644
--- a/plugins/mm-plugin-mbm.c
+++ b/plugins/mm-plugin-mbm.c
@@ -1,26 +1,24 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
- Additions to NetworkManager, network-manager-applet and modemmanager
- for supporting Ericsson modules like F3507g.
-
- Author: Per Hallsmark <per@hallsmark.se>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Copyright (C) 2008 Ericsson AB
+ *
+ * Author: Per Hallsmark <per.hallsmark@ericsson.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
#include <string.h>
#include <gmodule.h>
@@ -187,7 +185,7 @@ supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
gboolean supported = FALSE;
driver_name = get_driver (hal_ctx, udi);
- if (driver_name && !strcmp (driver_name, "mbm")) {
+ if (driver_name && (!strcmp (driver_name, "cdc_ether") || !strcmp (driver_name, "mbm"))) {
char **capabilities;
char **iter;
diff --git a/plugins/mm-plugin-mbm.h b/plugins/mm-plugin-mbm.h
index 72cd28f0..e0d2c56a 100644
--- a/plugins/mm-plugin-mbm.h
+++ b/plugins/mm-plugin-mbm.h
@@ -1,26 +1,24 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
- Additions to NetworkManager, network-manager-applet and modemmanager
- for supporting Ericsson modules like F3507g.
-
- Author: Per Hallsmark <per@hallsmark.se>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Copyright (C) 2008 Ericsson AB
+ *
+ * Author: Per Hallsmark <per.hallsmark@ericsson.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
#ifndef MM_PLUGIN_MBM_H
#define MM_PLUGIN_MBM_H