aboutsummaryrefslogtreecommitdiff
path: root/plugins/mm-modem-huawei.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/mm-modem-huawei.c')
-rw-r--r--plugins/mm-modem-huawei.c354
1 files changed, 152 insertions, 202 deletions
diff --git a/plugins/mm-modem-huawei.c b/plugins/mm-modem-huawei.c
index bbcb308c..480a4e71 100644
--- a/plugins/mm-modem-huawei.c
+++ b/plugins/mm-modem-huawei.c
@@ -5,8 +5,9 @@
#include <string.h>
#include "mm-modem-huawei.h"
#include "mm-modem-gsm-network.h"
-#include "mm-modem-error.h"
+#include "mm-errors.h"
#include "mm-callback-info.h"
+#include "mm-serial-parsers.h"
static gpointer mm_modem_huawei_parent_class = NULL;
@@ -14,7 +15,6 @@ static gpointer mm_modem_huawei_parent_class = NULL;
typedef struct {
MMSerial *monitor_device;
- guint watch_id;
} MMModemHuaweiPrivate;
enum {
@@ -43,25 +43,37 @@ mm_modem_huawei_new (const char *data_device,
/*****************************************************************************/
+typedef struct {
+ MMModemGsmNetwork *modem;
+ GRegex *r;
+} MonitorData;
+
static void
-parse_monitor_line (MMModemGsmNetwork *modem, char *buf)
+monitor_info_free (gpointer data)
{
- char **lines;
- char **iter;
+ MonitorData *info = (MonitorData *) data;
- lines = g_strsplit (buf, "\r\n", 0);
+ g_regex_unref (info->r);
+ g_slice_free (MonitorData, data);
+}
- for (iter = lines; iter && *iter; iter++) {
- char *line = *iter;
+static gboolean
+monitor_parse (gpointer data,
+ GString *response,
+ GError **error)
+{
+ MonitorData *info = (MonitorData *) data;
+ GMatchInfo *match_info;
+ gboolean found;
- g_strstrip (line);
- if (strlen (line) < 1 || line[0] != '^')
- continue;
+ found = g_regex_match_full (info->r, response->str, response->len, 0, 0, &match_info, NULL);
+ if (found) {
+ char *str;
- line += 1;
+ str = g_match_info_fetch (match_info, 1);
- if (!strncmp (line, "RSSI:", 5)) {
- int quality = atoi (line + 5);
+ if (g_str_has_prefix (str, "^RSSI:")) {
+ int quality = atoi (str + 6);
if (quality == 99)
/* 99 means unknown */
@@ -71,13 +83,13 @@ parse_monitor_line (MMModemGsmNetwork *modem, char *buf)
quality = quality * 100 / 31;
g_debug ("Signal quality: %d", quality);
- mm_modem_gsm_network_signal_quality (modem, (guint32) quality);
- } else if (!strncmp (line, "MODE:", 5)) {
+ mm_modem_gsm_network_signal_quality (info->modem, (guint32) quality);
+ } else if (g_str_has_prefix (str, "^MODE:")) {
MMModemGsmNetworkMode mode = 0;
int a;
int b;
- if (sscanf (line + 5, "%d,%d", &a, &b)) {
+ if (sscanf (str + 6, "%d,%d", &a, &b)) {
if (a == 3 && b == 2)
mode = MM_MODEM_GSM_NETWORK_MODE_GPRS;
else if (a == 3 && b == 3)
@@ -89,40 +101,17 @@ parse_monitor_line (MMModemGsmNetwork *modem, char *buf)
if (mode) {
g_debug ("Mode: %d", mode);
- mm_modem_gsm_network_mode (modem, mode);
+ mm_modem_gsm_network_mode (info->modem, mode);
}
}
}
- }
- g_strfreev (lines);
-}
+ g_free (str);
+ g_match_info_free (match_info);
-static gboolean
-monitor_device_got_data (GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- gsize bytes_read;
- char buf[4096];
- GIOStatus status;
-
- if (condition & G_IO_IN) {
- do {
- status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, NULL);
-
- if (bytes_read) {
- buf[bytes_read] = '\0';
- parse_monitor_line (MM_MODEM_GSM_NETWORK (data), buf);
- }
- } while (bytes_read == 4096 || status == G_IO_STATUS_AGAIN);
- }
-
- if (condition & G_IO_HUP || condition & G_IO_ERR) {
- return FALSE;
- }
-
- return TRUE;
+ }
+
+ return found;
}
static void
@@ -138,25 +127,16 @@ enable (MMModem *modem,
parent_modem_iface->enable (modem, enable, callback, user_data);
if (enable) {
- GIOChannel *channel;
-
- if (priv->watch_id == 0) {
- mm_serial_open (priv->monitor_device);
-
- channel = mm_serial_get_io_channel (priv->monitor_device);
- priv->watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP,
- monitor_device_got_data, modem);
+ GError *error = NULL;
- g_io_channel_unref (channel);
+ if (!mm_serial_open (priv->monitor_device, &error)) {
+ g_warning ("Could not open monitoring device %s: %s",
+ mm_serial_get_device (priv->monitor_device),
+ error->message);
+ g_error_free (error);
}
- } else {
- if (priv->watch_id) {
- g_source_remove (priv->watch_id);
- priv->watch_id = 0;
- mm_serial_close (priv->monitor_device);
- }
- }
-
+ } else
+ mm_serial_close (priv->monitor_device);
}
static gboolean
@@ -173,49 +153,42 @@ parse_syscfg (const char *reply, int *mode_a, int *mode_b, guint32 *band, int *u
static void
set_network_mode_done (MMSerial *serial,
- int reply_index,
+ GString *response,
+ GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- switch (reply_index) {
- case 0:
- /* Success */
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting network mode failed");
- break;
- }
+ if (error)
+ info->error = g_error_copy (error);
mm_callback_info_schedule (info);
}
static void
-set_network_mode_get_done (MMSerial *serial, const char *reply, gpointer user_data)
+set_network_mode_get_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- int a, b, u1, u2;
- guint32 band;
- guint id = 0;
- if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
- char *responses[] = { "OK", "ERROR", NULL };
- char *command;
-
- a = GPOINTER_TO_INT (mm_callback_info_get_data (info, "mode-a"));
- b = GPOINTER_TO_INT (mm_callback_info_get_data (info, "mode-b"));
- command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
+ if (error) {
+ info->error = g_error_copy (error);
+ mm_callback_info_schedule (info);
+ } else {
+ int a, b, u1, u2;
+ guint32 band;
- if (mm_serial_send_command_string (serial, command))
- id = mm_serial_wait_for_reply (serial, 3, responses, responses, set_network_mode_done, info);
+ if (parse_syscfg (response->str, &a, &b, &band, &u1, &u2)) {
+ char *command;
- g_free (command);
- }
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Could not set network mode");
- mm_callback_info_schedule (info);
+ a = GPOINTER_TO_INT (mm_callback_info_get_data (info, "mode-a"));
+ b = GPOINTER_TO_INT (mm_callback_info_get_data (info, "mode-b"));
+ command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
+ mm_serial_queue_command (serial, command, 3, set_network_mode_done, info);
+ g_free (command);
+ }
}
}
@@ -226,8 +199,6 @@ set_network_mode (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
@@ -262,39 +233,41 @@ set_network_mode (MMModemGsmNetwork *modem,
break;
}
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, set_network_mode_get_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting network mode failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, set_network_mode_get_done, info);
}
static void
-get_network_mode_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_network_mode_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- int a, b, u1, u2;
- guint32 band;
- guint32 result = 0;
-
- if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
- if (a == 2 && b == 1)
- result = MM_MODEM_GSM_NETWORK_MODE_PREFER_2G;
- else if (a == 2 && b == 2)
- result = MM_MODEM_GSM_NETWORK_MODE_PREFER_3G;
- else if (a == 13 && b == 1)
- result = MM_MODEM_GSM_NETWORK_MODE_GPRS;
- else if (a == 14 && b == 2)
- result = MM_MODEM_GSM_NETWORK_MODE_3G;
- }
- if (result == 0)
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Could not parse network mode results");
- else
- mm_callback_info_set_result (info, GUINT_TO_POINTER (result), NULL);
+ if (error)
+ info->error = g_error_copy (error);
+ else {
+ int a, b, u1, u2;
+ guint32 band;
+ guint32 result = 0;
+
+ if (parse_syscfg (response->str, &a, &b, &band, &u1, &u2)) {
+ if (a == 2 && b == 1)
+ result = MM_MODEM_GSM_NETWORK_MODE_PREFER_2G;
+ else if (a == 2 && b == 2)
+ result = MM_MODEM_GSM_NETWORK_MODE_PREFER_3G;
+ else if (a == 13 && b == 1)
+ result = MM_MODEM_GSM_NETWORK_MODE_GPRS;
+ else if (a == 14 && b == 2)
+ result = MM_MODEM_GSM_NETWORK_MODE_3G;
+ }
+
+ if (result == 0)
+ info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "%s", "Could not parse network mode results");
+ else
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (result), NULL);
+ }
mm_callback_info_schedule (info);
}
@@ -305,64 +278,48 @@ get_network_mode (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, get_network_mode_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Getting network mode failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, get_network_mode_done, info);
}
static void
set_band_done (MMSerial *serial,
- int reply_index,
+ GString *response,
+ GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- switch (reply_index) {
- case 0:
- /* Success */
- break;
- default:
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting band failed");
- break;
- }
+ if (error)
+ info->error = g_error_copy (error);
mm_callback_info_schedule (info);
}
static void
-set_band_get_done (MMSerial *serial, const char *reply, gpointer user_data)
+set_band_get_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- int a, b, u1, u2;
- guint32 band;
- guint id = 0;
-
- if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
- char *responses[] = { "OK", "ERROR", NULL };
- char *command;
-
- band = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"));
- command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
- if (mm_serial_send_command_string (serial, command))
- id = mm_serial_wait_for_reply (serial, 3, responses, responses, set_band_done, info);
+ if (error) {
+ info->error = g_error_copy (error);
+ mm_callback_info_schedule (info);
+ } else {
+ int a, b, u1, u2;
+ guint32 band;
- g_free (command);
- }
+ if (parse_syscfg (response->str, &a, &b, &band, &u1, &u2)) {
+ char *command;
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Could not set band");
- mm_callback_info_schedule (info);
+ band = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"));
+ command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
+ mm_serial_queue_command (serial, command, 3, set_band_done, info);
+ g_free (command);
+ }
}
}
@@ -373,8 +330,6 @@ set_band (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
@@ -397,37 +352,39 @@ set_band (MMModemGsmNetwork *modem,
break;
}
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, set_band_get_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting band failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, set_band_get_done, info);
}
static void
-get_band_done (MMSerial *serial, const char *reply, gpointer user_data)
+get_band_done (MMSerial *serial,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- int a, b, u1, u2;
- guint32 band;
- guint32 result = 0xdeadbeaf;
-
- if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
- if (band == 0x3FFFFFFF)
- result = MM_MODEM_GSM_NETWORK_BAND_ANY;
- else if (band == 0x400380)
- result = MM_MODEM_GSM_NETWORK_BAND_DCS;
- else if (band == 0x200000)
- result = MM_MODEM_GSM_NETWORK_BAND_PCS;
- }
- if (result == 0xdeadbeaf)
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "%s", "Could not parse band results");
- else
- mm_callback_info_set_result (info, GUINT_TO_POINTER (result), NULL);
+ if (error)
+ info->error = g_error_copy (error);
+ else {
+ int a, b, u1, u2;
+ guint32 band;
+ guint32 result = 0xdeadbeaf;
+
+ if (parse_syscfg (response->str, &a, &b, &band, &u1, &u2)) {
+ if (band == 0x3FFFFFFF)
+ result = MM_MODEM_GSM_NETWORK_BAND_ANY;
+ else if (band == 0x400380)
+ result = MM_MODEM_GSM_NETWORK_BAND_DCS;
+ else if (band == 0x200000)
+ result = MM_MODEM_GSM_NETWORK_BAND_PCS;
+ }
+
+ if (result == 0xdeadbeaf)
+ info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "%s", "Could not parse band results");
+ else
+ mm_callback_info_set_result (info, GUINT_TO_POINTER (result), NULL);
+ }
mm_callback_info_schedule (info);
}
@@ -438,18 +395,9 @@ get_band (MMModemGsmNetwork *modem,
gpointer user_data)
{
MMCallbackInfo *info;
- char *terminators = "\r\n";
- guint id = 0;
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
-
- if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
- id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, get_band_done, info);
-
- if (!id) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Getting band failed.");
- mm_callback_info_schedule (info);
- }
+ mm_serial_queue_command (MM_SERIAL (modem), "AT^SYSCFG?", 3, get_band_done, info);
}
/*****************************************************************************/
@@ -481,6 +429,7 @@ constructor (GType type,
{
GObject *object;
MMModemHuaweiPrivate *priv;
+ MonitorData *info;
object = G_OBJECT_CLASS (mm_modem_huawei_parent_class)->constructor (type,
n_construct_params,
@@ -496,6 +445,11 @@ constructor (GType type,
return NULL;
}
+ info = g_slice_new (MonitorData);
+ info->modem = MM_MODEM_GSM_NETWORK (object);
+ info->r = g_regex_new ("\\r\\n(.+)\r\n$", G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_serial_set_response_parser (priv->monitor_device, monitor_parse, info, monitor_info_free);
+
return object;
}
@@ -538,14 +492,10 @@ finalize (GObject *object)
{
MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (object);
- if (priv->watch_id) {
- g_source_remove (priv->watch_id);
- priv->watch_id = 0;
+ if (priv->monitor_device) {
mm_serial_close (priv->monitor_device);
- }
-
- if (priv->monitor_device)
g_object_unref (priv->monitor_device);
+ }
G_OBJECT_CLASS (mm_modem_huawei_parent_class)->finalize (object);
}