serial: refactor MMSerialPort into a base class and an AT-capable serial port

For QCDM devices we want most of what MMSerialPort does, but not
the AT command handling stuff since the commands and responses
aren't AT commands nor are they even strings.  So convert everything
that MMSerialPort does into a GByteArray, and let MMAtSerialPort
handle the conversion to strings when necessary.
This commit is contained in:
Dan Williams
2010-02-20 14:55:10 -08:00
parent a431455059
commit a8c7bba19e
24 changed files with 983 additions and 618 deletions
+4 -2
View File
@@ -35,12 +35,14 @@ modem_manager_SOURCES = \
mm-modem.h \
mm-port.c \
mm-port.h \
mm-modem-base.c \
mm-modem-base.h \
mm-serial-port.c \
mm-serial-port.h \
mm-at-serial-port.c \
mm-at-serial-port.h \
mm-serial-parsers.c \
mm-serial-parsers.h \
mm-modem-base.c \
mm-modem-base.h \
mm-generic-cdma.c \
mm-generic-cdma.h \
mm-generic-gsm.c \
+323
View File
@@ -0,0 +1,323 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2008 - 2009 Novell, Inc.
* Copyright (C) 2009 Red Hat, Inc.
*/
#define _GNU_SOURCE /* for strcasestr() */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "mm-at-serial-port.h"
#include "mm-errors.h"
#include "mm-options.h"
G_DEFINE_TYPE (MMAtSerialPort, mm_at_serial_port, MM_TYPE_SERIAL_PORT)
#define MM_AT_SERIAL_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPortPrivate))
typedef struct {
/* Response parser data */
MMAtSerialResponseParserFn response_parser_fn;
gpointer response_parser_user_data;
GDestroyNotify response_parser_notify;
GSList *unsolicited_msg_handlers;
} MMAtSerialPortPrivate;
/*****************************************************************************/
void
mm_at_serial_port_set_response_parser (MMAtSerialPort *self,
MMAtSerialResponseParserFn fn,
gpointer user_data,
GDestroyNotify notify)
{
MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
if (priv->response_parser_notify)
priv->response_parser_notify (priv->response_parser_user_data);
priv->response_parser_fn = fn;
priv->response_parser_user_data = user_data;
priv->response_parser_notify = notify;
}
static gboolean
parse_response (MMSerialPort *port, GByteArray *response, GError **error)
{
MMAtSerialPort *self = MM_AT_SERIAL_PORT (port);
MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
gboolean found;
GString *string;
g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE);
/* Construct the string that AT-parsing functions expect */
string = g_string_sized_new (response->len + 1);
g_string_append_len (string, (const char *) response->data, response->len);
/* Parse it */
found = priv->response_parser_fn (priv->response_parser_user_data, string, error);
/* And copy it back into the response array after the parser has removed
* matches and cleaned it up.
*/
g_byte_array_remove_range (response, 0, response->len);
g_byte_array_append (response, (const guint8 *) string->str, string->len);
g_string_free (string, TRUE);
return found;
}
static void
handle_response (MMSerialPort *port,
GByteArray *response,
GError *error,
GCallback callback,
gpointer callback_data)
{
MMAtSerialPort *self = MM_AT_SERIAL_PORT (port);
MMAtSerialResponseFn response_callback = (MMAtSerialResponseFn) callback;
GString *string;
/* Convert to a string and call the callback */
string = g_string_sized_new (response->len + 1);
g_string_append_len (string, (const char *) response->data, response->len);
response_callback (self, string, error, callback_data);
g_string_free (string, TRUE);
}
/*****************************************************************************/
typedef struct {
GRegex *regex;
MMAtSerialUnsolicitedMsgFn callback;
gpointer user_data;
GDestroyNotify notify;
} MMAtUnsolicitedMsgHandler;
void
mm_at_serial_port_add_unsolicited_msg_handler (MMAtSerialPort *self,
GRegex *regex,
MMAtSerialUnsolicitedMsgFn callback,
gpointer user_data,
GDestroyNotify notify)
{
MMAtUnsolicitedMsgHandler *handler;
MMAtSerialPortPrivate *priv;
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
g_return_if_fail (regex != NULL);
handler = g_slice_new (MMAtUnsolicitedMsgHandler);
handler->regex = g_regex_ref (regex);
handler->callback = callback;
handler->user_data = user_data;
handler->notify = notify;
priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler);
}
static gboolean
remove_eval_cb (const GMatchInfo *match_info,
GString *result,
gpointer user_data)
{
int *result_len = (int *) user_data;
int start;
int end;
if (g_match_info_fetch_pos (match_info, 0, &start, &end))
*result_len -= (end - start);
return FALSE;
}
static void
parse_unsolicited (MMSerialPort *port, GByteArray *response)
{
MMAtSerialPort *self = MM_AT_SERIAL_PORT (port);
MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
GSList *iter;
for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) {
MMAtUnsolicitedMsgHandler *handler = (MMAtUnsolicitedMsgHandler *) iter->data;
GMatchInfo *match_info;
gboolean matches;
matches = g_regex_match_full (handler->regex,
(const char *) response->data,
response->len,
0, 0, &match_info, NULL);
if (handler->callback) {
while (g_match_info_matches (match_info)) {
handler->callback (self, match_info, handler->user_data);
g_match_info_next (match_info, NULL);
}
}
g_match_info_free (match_info);
if (matches) {
/* Remove matches */
char *str;
int result_len = response->len;
str = g_regex_replace_eval (handler->regex,
(const char *) response->data,
response->len,
0, 0,
remove_eval_cb, &result_len, NULL);
g_byte_array_remove_range (response, 0, response->len);
g_byte_array_append (response, (const guint8 *) str, result_len);
g_free (str);
}
}
}
/*****************************************************************************/
static GByteArray *
at_command_to_byte_array (const char *command)
{
GByteArray *buf;
int cmdlen;
g_return_val_if_fail (command != NULL, NULL);
cmdlen = strlen (command);
buf = g_byte_array_sized_new (cmdlen + 3);
/* Make sure there's an AT in the front */
if (!g_str_has_prefix (command, "AT"))
g_byte_array_append (buf, (const guint8 *) "AT", 2);
g_byte_array_append (buf, (const guint8 *) command, cmdlen);
/* Make sure there's a trailing carriage return */
if (command[cmdlen] != '\r')
g_byte_array_append (buf, (const guint8 *) "\r", 1);
return buf;
}
void
mm_at_serial_port_queue_command (MMAtSerialPort *self,
const char *command,
guint32 timeout_seconds,
MMAtSerialResponseFn callback,
gpointer user_data)
{
GByteArray *buf;
g_return_if_fail (self != NULL);
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
g_return_if_fail (command != NULL);
buf = at_command_to_byte_array (command);
g_return_if_fail (buf != NULL);
mm_serial_port_queue_command (MM_SERIAL_PORT (self),
buf,
TRUE,
timeout_seconds,
G_CALLBACK (callback),
user_data);
}
void
mm_at_serial_port_queue_command_cached (MMAtSerialPort *self,
const char *command,
guint32 timeout_seconds,
MMAtSerialResponseFn callback,
gpointer user_data)
{
GByteArray *buf;
g_return_if_fail (self != NULL);
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
g_return_if_fail (command != NULL);
buf = at_command_to_byte_array (command);
g_return_if_fail (buf != NULL);
mm_serial_port_queue_command_cached (MM_SERIAL_PORT (self),
buf,
TRUE,
timeout_seconds,
G_CALLBACK (callback),
user_data);
}
/*****************************************************************************/
MMAtSerialPort *
mm_at_serial_port_new (const char *name, MMPortType ptype)
{
return MM_AT_SERIAL_PORT (g_object_new (MM_TYPE_AT_SERIAL_PORT,
MM_PORT_DEVICE, name,
MM_PORT_SUBSYS, MM_PORT_SUBSYS_TTY,
MM_PORT_TYPE, ptype,
NULL));
}
static void
mm_at_serial_port_init (MMAtSerialPort *self)
{
}
static void
finalize (GObject *object)
{
MMAtSerialPort *self = MM_AT_SERIAL_PORT (object);
MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
while (priv->unsolicited_msg_handlers) {
MMAtUnsolicitedMsgHandler *handler = (MMAtUnsolicitedMsgHandler *) priv->unsolicited_msg_handlers->data;
if (handler->notify)
handler->notify (handler->user_data);
g_regex_unref (handler->regex);
g_slice_free (MMAtUnsolicitedMsgHandler, handler);
priv->unsolicited_msg_handlers = g_slist_delete_link (priv->unsolicited_msg_handlers,
priv->unsolicited_msg_handlers);
}
if (priv->response_parser_notify)
priv->response_parser_notify (priv->response_parser_user_data);
G_OBJECT_CLASS (mm_at_serial_port_parent_class)->finalize (object);
}
static void
mm_at_serial_port_class_init (MMAtSerialPortClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MMSerialPortClass *port_class = MM_SERIAL_PORT_CLASS (klass);
g_type_class_add_private (object_class, sizeof (MMAtSerialPortPrivate));
/* Virtual methods */
object_class->finalize = finalize;
port_class->parse_unsolicited = parse_unsolicited;
port_class->parse_response = parse_response;
port_class->handle_response = handle_response;
}
+85
View File
@@ -0,0 +1,85 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2008 - 2009 Novell, Inc.
* Copyright (C) 2009 - 2010 Red Hat, Inc.
*/
#ifndef MM_AT_SERIAL_PORT_H
#define MM_AT_SERIAL_PORT_H
#include <glib.h>
#include <glib/gtypes.h>
#include <glib-object.h>
#include "mm-serial-port.h"
#define MM_TYPE_AT_SERIAL_PORT (mm_at_serial_port_get_type ())
#define MM_AT_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPort))
#define MM_AT_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPortClass))
#define MM_IS_AT_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_AT_SERIAL_PORT))
#define MM_IS_AT_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_AT_SERIAL_PORT))
#define MM_AT_SERIAL_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPortClass))
typedef struct _MMAtSerialPort MMAtSerialPort;
typedef struct _MMAtSerialPortClass MMAtSerialPortClass;
typedef gboolean (*MMAtSerialResponseParserFn) (gpointer user_data,
GString *response,
GError **error);
typedef void (*MMAtSerialUnsolicitedMsgFn) (MMAtSerialPort *port,
GMatchInfo *match_info,
gpointer user_data);
typedef void (*MMAtSerialResponseFn) (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data);
struct _MMAtSerialPort {
MMSerialPort parent;
};
struct _MMAtSerialPortClass {
MMSerialPortClass parent;
};
GType mm_at_serial_port_get_type (void);
MMAtSerialPort *mm_at_serial_port_new (const char *name, MMPortType ptype);
void mm_at_serial_port_add_unsolicited_msg_handler (MMAtSerialPort *self,
GRegex *regex,
MMAtSerialUnsolicitedMsgFn callback,
gpointer user_data,
GDestroyNotify notify);
void mm_at_serial_port_set_response_parser (MMAtSerialPort *self,
MMAtSerialResponseParserFn fn,
gpointer user_data,
GDestroyNotify notify);
void mm_at_serial_port_queue_command (MMAtSerialPort *self,
const char *command,
guint32 timeout_seconds,
MMAtSerialResponseFn callback,
gpointer user_data);
void mm_at_serial_port_queue_command_cached (MMAtSerialPort *self,
const char *command,
guint32 timeout_seconds,
MMAtSerialResponseFn callback,
gpointer user_data);
#endif /* MM_AT_SERIAL_PORT_H */
+47 -47
View File
@@ -23,7 +23,7 @@
#include "mm-generic-cdma.h"
#include "mm-modem-cdma.h"
#include "mm-modem-simple.h"
#include "mm-serial-port.h"
#include "mm-at-serial-port.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
#include "mm-serial-parsers.h"
@@ -67,8 +67,8 @@ typedef struct {
guint reg_state_changed_id;
MMCallbackInfo *simple_connect_info;
MMSerialPort *primary;
MMSerialPort *secondary;
MMAtSerialPort *primary;
MMAtSerialPort *secondary;
MMPort *data;
} MMGenericCdmaPrivate;
@@ -148,22 +148,22 @@ mm_generic_cdma_grab_port (MMGenericCdma *self,
}
port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype);
if (port && MM_IS_SERIAL_PORT (port)) {
if (port && MM_IS_AT_SERIAL_PORT (port)) {
g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL);
mm_serial_port_set_response_parser (MM_SERIAL_PORT (port),
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port),
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
if (ptype == MM_PORT_TYPE_PRIMARY) {
priv->primary = MM_SERIAL_PORT (port);
priv->primary = MM_AT_SERIAL_PORT (port);
if (!priv->data) {
priv->data = port;
g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
}
check_valid (self);
} else if (ptype == MM_PORT_TYPE_SECONDARY)
priv->secondary = MM_SERIAL_PORT (port);
priv->secondary = MM_AT_SERIAL_PORT (port);
} else {
/* Net device (if any) is the preferred data port */
if (!priv->data || MM_IS_SERIAL_PORT (priv->data)) {
@@ -215,9 +215,9 @@ release_port (MMModem *modem, const char *subsys, const char *name)
check_valid (MM_GENERIC_CDMA (modem));
}
MMSerialPort *
mm_generic_cdma_get_port (MMGenericCdma *modem,
MMPortType ptype)
MMAtSerialPort *
mm_generic_cdma_get_at_port (MMGenericCdma *modem,
MMPortType ptype)
{
g_return_val_if_fail (MM_IS_GENERIC_CDMA (modem), NULL);
g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL);
@@ -360,7 +360,7 @@ enable_all_done (MMModem *modem, GError *error, gpointer user_data)
else {
/* Open up the second port, if one exists */
if (priv->secondary) {
if (!mm_serial_port_open (priv->secondary, &info->error)) {
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &info->error)) {
g_assert (info->error);
goto out;
}
@@ -380,7 +380,7 @@ out:
}
static void
enable_error_reporting_done (MMSerialPort *port,
enable_error_reporting_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -399,7 +399,7 @@ enable_error_reporting_done (MMSerialPort *port,
}
static void
init_done (MMSerialPort *port,
init_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -419,7 +419,7 @@ init_done (MMSerialPort *port,
FIXME: It's mandatory by spec, so it really shouldn't be optional. Figure
out which CDMA modems have problems with it and implement plugin for them.
*/
mm_serial_port_queue_command (port, "+CMEE=1", 3, enable_error_reporting_done, user_data);
mm_at_serial_port_queue_command (port, "+CMEE=1", 3, enable_error_reporting_done, user_data);
}
}
@@ -439,7 +439,7 @@ flash_done (MMSerialPort *port, GError *error, gpointer user_data)
return;
}
mm_serial_port_queue_command (port, "Z E0 V1 X4 &C1", 3, init_done, user_data);
mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "Z E0 V1 X4 &C1", 3, init_done, user_data);
}
static void
@@ -453,7 +453,7 @@ enable (MMModem *modem,
info = mm_callback_info_new (modem, callback, user_data);
if (!mm_serial_port_open (priv->primary, &info->error)) {
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &info->error)) {
g_assert (info->error);
mm_callback_info_schedule (info);
return;
@@ -463,7 +463,7 @@ enable (MMModem *modem,
MM_MODEM_STATE_ENABLING,
MM_MODEM_STATE_REASON_NONE);
mm_serial_port_flash (priv->primary, 100, flash_done, info);
mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 100, flash_done, info);
}
static void
@@ -489,7 +489,7 @@ disable_all_done (MMModem *modem, GError *error, gpointer user_data)
MMGenericCdma *self = MM_GENERIC_CDMA (info->modem);
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self);
mm_serial_port_close (priv->primary);
mm_serial_port_close (MM_SERIAL_PORT (priv->primary));
mm_modem_set_state (modem, MM_MODEM_STATE_DISABLED, MM_MODEM_STATE_REASON_NONE);
priv->cdma_1x_reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
@@ -546,20 +546,20 @@ disable (MMModem *modem,
NULL);
if (priv->secondary)
mm_serial_port_close (priv->secondary);
mm_serial_port_close (MM_SERIAL_PORT (priv->secondary));
mm_modem_set_state (MM_MODEM (info->modem),
MM_MODEM_STATE_DISABLING,
MM_MODEM_STATE_REASON_NONE);
if (mm_port_get_connected (MM_PORT (priv->primary)))
mm_serial_port_flash (priv->primary, 1000, disable_flash_done, info);
mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disable_flash_done, info);
else
disable_flash_done (priv->primary, NULL, info);
disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info);
}
static void
dial_done (MMSerialPort *port,
dial_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -598,7 +598,7 @@ connect (MMModem *modem,
info = mm_callback_info_new (modem, callback, user_data);
command = g_strconcat ("DT", number, NULL);
mm_serial_port_queue_command (priv->primary, command, 90, dial_done, info);
mm_at_serial_port_queue_command (priv->primary, command, 90, dial_done, info);
g_free (command);
}
@@ -648,7 +648,7 @@ disconnect (MMModem *modem,
NULL);
mm_modem_set_state (modem, MM_MODEM_STATE_DISCONNECTING, MM_MODEM_STATE_REASON_NONE);
mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info);
mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disconnect_flash_done, info);
}
static void
@@ -678,7 +678,7 @@ strip_response (const char *resp, const char *cmd)
}
static void
get_version_done (MMSerialPort *port,
get_version_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -696,7 +696,7 @@ get_version_done (MMSerialPort *port,
}
static void
get_model_done (MMSerialPort *port,
get_model_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -712,7 +712,7 @@ get_model_done (MMSerialPort *port,
}
static void
get_manufacturer_done (MMSerialPort *port,
get_manufacturer_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -734,7 +734,7 @@ get_card_info (MMModem *modem,
{
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
MMSerialPort *port = priv->primary;
MMAtSerialPort *port = priv->primary;
info = mm_callback_info_new_full (MM_MODEM (modem),
card_info_invoke,
@@ -753,9 +753,9 @@ get_card_info (MMModem *modem,
port = priv->secondary;
}
mm_serial_port_queue_command_cached (port, "+GMI", 3, get_manufacturer_done, info);
mm_serial_port_queue_command_cached (port, "+GMM", 3, get_model_done, info);
mm_serial_port_queue_command_cached (port, "+GMR", 3, get_version_done, info);
mm_at_serial_port_queue_command_cached (port, "+GMI", 3, get_manufacturer_done, info);
mm_at_serial_port_queue_command_cached (port, "+GMM", 3, get_model_done, info);
mm_at_serial_port_queue_command_cached (port, "+GMR", 3, get_version_done, info);
}
/*****************************************************************************/
@@ -793,7 +793,7 @@ mm_generic_cdma_update_evdo_quality (MMGenericCdma *self, guint32 quality)
#define CSQ2_TRIED "csq?-tried"
static void
get_signal_quality_done (MMSerialPort *port,
get_signal_quality_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -811,7 +811,7 @@ get_signal_quality_done (MMSerialPort *port,
* try the other command if the first one fails.
*/
mm_callback_info_set_data (info, CSQ2_TRIED, GUINT_TO_POINTER (1), NULL);
mm_serial_port_queue_command (port, "+CSQ?", 3, get_signal_quality_done, info);
mm_at_serial_port_queue_command (port, "+CSQ?", 3, get_signal_quality_done, info);
return;
}
} else {
@@ -853,7 +853,7 @@ get_signal_quality (MMModemCdma *modem,
{
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
MMSerialPort *port = priv->primary;
MMAtSerialPort *port = priv->primary;
if (mm_port_get_connected (MM_PORT (priv->primary))) {
if (!priv->secondary) {
@@ -867,11 +867,11 @@ get_signal_quality (MMModemCdma *modem,
}
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
mm_serial_port_queue_command (port, "+CSQ", 3, get_signal_quality_done, info);
mm_at_serial_port_queue_command (port, "+CSQ", 3, get_signal_quality_done, info);
}
static void
get_string_done (MMSerialPort *port,
get_string_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -897,7 +897,7 @@ get_esn (MMModemCdma *modem,
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
GError *error;
MMSerialPort *port = priv->primary;
MMAtSerialPort *port = priv->primary;
if (mm_port_get_connected (MM_PORT (priv->primary))) {
if (!priv->secondary) {
@@ -913,7 +913,7 @@ get_esn (MMModemCdma *modem,
}
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
mm_serial_port_queue_command_cached (port, "+GSN", 3, get_string_done, info);
mm_at_serial_port_queue_command_cached (port, "+GSN", 3, get_string_done, info);
}
static void
@@ -997,7 +997,7 @@ convert_sid (const char *sid)
}
static void
serving_system_done (MMSerialPort *port,
serving_system_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1116,7 +1116,7 @@ get_serving_system (MMModemCdma *modem,
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
GError *error;
MMSerialPort *port = priv->primary;
MMAtSerialPort *port = priv->primary;
if (mm_port_get_connected (MM_PORT (priv->primary))) {
if (!priv->secondary) {
@@ -1136,7 +1136,7 @@ get_serving_system (MMModemCdma *modem,
G_CALLBACK (callback),
user_data);
mm_serial_port_queue_command (port, "+CSS?", 3, serving_system_done, info);
mm_at_serial_port_queue_command (port, "+CSS?", 3, serving_system_done, info);
}
#define CDMA_1X_STATE_TAG "cdma-1x-reg-state"
@@ -1298,7 +1298,7 @@ reg_state_css_response (MMModemCdma *cdma,
}
static void
get_analog_digital_done (MMSerialPort *port,
get_analog_digital_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1365,7 +1365,7 @@ get_registration_state (MMModemCdma *modem,
{
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
MMSerialPort *port = priv->primary;
MMAtSerialPort *port = priv->primary;
if (mm_port_get_connected (MM_PORT (priv->primary))) {
if (!priv->secondary) {
@@ -1380,7 +1380,7 @@ get_registration_state (MMModemCdma *modem,
}
info = mm_generic_cdma_query_reg_state_callback_info_new (MM_GENERIC_CDMA (modem), callback, user_data);
mm_serial_port_queue_command (port, "+CAD?", 3, get_analog_digital_done, info);
mm_at_serial_port_queue_command (port, "+CAD?", 3, get_analog_digital_done, info);
}
/*****************************************************************************/
+2 -2
View File
@@ -20,7 +20,7 @@
#include "mm-modem.h"
#include "mm-modem-base.h"
#include "mm-modem-cdma.h"
#include "mm-serial-port.h"
#include "mm-at-serial-port.h"
#include "mm-callback-info.h"
#define MM_TYPE_GENERIC_CDMA (mm_generic_cdma_get_type ())
@@ -80,7 +80,7 @@ MMPort * mm_generic_cdma_grab_port (MMGenericCdma *self,
gpointer user_data,
GError **error);
MMSerialPort *mm_generic_cdma_get_port (MMGenericCdma *modem, MMPortType ptype);
MMAtSerialPort *mm_generic_cdma_get_at_port (MMGenericCdma *modem, MMPortType ptype);
void mm_generic_cdma_update_cdma1x_quality (MMGenericCdma *self, guint32 quality);
void mm_generic_cdma_update_evdo_quality (MMGenericCdma *self, guint32 quality);
+94 -88
View File
@@ -26,6 +26,7 @@
#include "mm-modem-simple.h"
#include "mm-errors.h"
#include "mm-callback-info.h"
#include "mm-at-serial-port.h"
#include "mm-serial-parsers.h"
#include "mm-modem-helpers.h"
@@ -66,23 +67,23 @@ typedef struct {
guint32 signal_quality;
guint32 cid;
MMSerialPort *primary;
MMSerialPort *secondary;
MMAtSerialPort *primary;
MMAtSerialPort *secondary;
MMPort *data;
} MMGenericGsmPrivate;
static void get_registration_status (MMSerialPort *port, MMCallbackInfo *info);
static void read_operator_code_done (MMSerialPort *port,
static void get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info);
static void read_operator_code_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data);
static void read_operator_name_done (MMSerialPort *port,
static void read_operator_name_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data);
static void reg_state_changed (MMSerialPort *port,
static void reg_state_changed (MMAtSerialPort *port,
GMatchInfo *match_info,
gpointer user_data);
@@ -152,8 +153,8 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *modem,
if (status == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
mm_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem);
mm_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem);
mm_at_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem);
mm_at_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem);
mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL);
} else {
g_free (priv->oper_code);
@@ -175,7 +176,7 @@ typedef struct {
} CPinResult;
static void
pin_check_done (MMSerialPort *port,
pin_check_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -252,7 +253,7 @@ mm_generic_gsm_check_pin (MMGenericGsm *modem,
priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
mm_serial_port_queue_command (priv->primary, "+CPIN?", 3, pin_check_done, info);
mm_at_serial_port_queue_command (priv->primary, "+CPIN?", 3, pin_check_done, info);
}
/*****************************************************************************/
@@ -338,7 +339,7 @@ initial_pin_check_done (MMModem *modem, GError *error, gpointer user_data)
} else {
priv->pin_checked = TRUE;
if (close_port)
mm_serial_port_close (priv->primary);
mm_serial_port_close (MM_SERIAL_PORT (priv->primary));
check_valid (MM_GENERIC_GSM (modem));
}
}
@@ -354,7 +355,7 @@ initial_pin_check (MMGenericGsm *self)
g_return_if_fail (priv->primary != NULL);
if (mm_serial_port_open (priv->primary, &error))
if (mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &error))
mm_generic_gsm_check_pin (self, initial_pin_check_done, GUINT_TO_POINTER (TRUE));
else {
g_warning ("%s: failed to open serial port: (%d) %s",
@@ -390,18 +391,20 @@ mm_generic_gsm_grab_port (MMGenericGsm *self,
g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), FALSE);
port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype);
if (port && MM_IS_SERIAL_PORT (port)) {
mm_serial_port_set_response_parser (MM_SERIAL_PORT (port),
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
if (port && MM_IS_AT_SERIAL_PORT (port)) {
mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port),
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
regex = g_regex_new ("\\r\\n\\+CREG: (\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, reg_state_changed, self, NULL);
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port),
regex, reg_state_changed,
self, NULL);
g_regex_unref (regex);
if (ptype == MM_PORT_TYPE_PRIMARY) {
priv->primary = MM_SERIAL_PORT (port);
priv->primary = MM_AT_SERIAL_PORT (port);
if (!priv->data) {
priv->data = port;
g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
@@ -411,7 +414,7 @@ mm_generic_gsm_grab_port (MMGenericGsm *self,
initial_pin_check (self);
} else if (ptype == MM_PORT_TYPE_SECONDARY)
priv->secondary = MM_SERIAL_PORT (port);
priv->secondary = MM_AT_SERIAL_PORT (port);
} else {
/* Net device (if any) is the preferred data port */
if (!priv->data || MM_IS_SERIAL_PORT (priv->data)) {
@@ -508,7 +511,7 @@ mm_generic_gsm_enable_complete (MMGenericGsm *modem,
}
static void
enable_done (MMSerialPort *port,
enable_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -528,7 +531,7 @@ enable_done (MMSerialPort *port,
}
static void
init_done (MMSerialPort *port,
init_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -544,20 +547,20 @@ init_done (MMSerialPort *port,
/* Ensure echo is off after the init command; some modems ignore the
* E0 when it's in the same like as ATZ (Option GIO322).
*/
mm_serial_port_queue_command (port, "E0 +CMEE=1", 2, NULL, NULL);
mm_at_serial_port_queue_command (port, "E0 +CMEE=1", 2, NULL, NULL);
g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_INIT_CMD_OPTIONAL, &cmd, NULL);
mm_serial_port_queue_command (port, cmd, 2, NULL, NULL);
mm_at_serial_port_queue_command (port, cmd, 2, NULL, NULL);
g_free (cmd);
if (MM_GENERIC_GSM_GET_PRIVATE (info->modem)->unsolicited_registration)
mm_serial_port_queue_command (port, "+CREG=1", 5, NULL, NULL);
mm_at_serial_port_queue_command (port, "+CREG=1", 5, NULL, NULL);
else
mm_serial_port_queue_command (port, "+CREG=0", 5, NULL, NULL);
mm_at_serial_port_queue_command (port, "+CREG=0", 5, NULL, NULL);
g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL);
if (cmd && strlen (cmd))
mm_serial_port_queue_command (port, cmd, 5, enable_done, user_data);
mm_at_serial_port_queue_command (port, cmd, 5, enable_done, user_data);
else
enable_done (port, NULL, NULL, user_data);
g_free (cmd);
@@ -575,7 +578,7 @@ enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data)
}
g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_INIT_CMD, &cmd, NULL);
mm_serial_port_queue_command (port, cmd, 3, init_done, user_data);
mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), cmd, 3, init_done, user_data);
g_free (cmd);
}
@@ -586,7 +589,7 @@ real_do_enable (MMGenericGsm *self, MMModemFn callback, gpointer user_data)
MMCallbackInfo *info;
info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
mm_serial_port_flash (priv->primary, 100, enable_flash_done, info);
mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 100, enable_flash_done, info);
}
static void
@@ -600,7 +603,7 @@ enable (MMModem *modem,
/* First, reset the previously used CID */
mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0);
if (!mm_serial_port_open (priv->primary, &error)) {
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &error)) {
MMCallbackInfo *info;
g_assert (error);
@@ -617,7 +620,7 @@ enable (MMModem *modem,
}
static void
disable_done (MMSerialPort *port,
disable_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -628,7 +631,7 @@ disable_done (MMSerialPort *port,
if (!info->error) {
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
mm_serial_port_close (port);
mm_serial_port_close (MM_SERIAL_PORT (port));
mm_modem_set_state (MM_MODEM (info->modem),
MM_MODEM_STATE_DISABLED,
MM_MODEM_STATE_REASON_NONE);
@@ -662,9 +665,9 @@ disable_flash_done (MMSerialPort *port,
g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_DOWN_CMD, &cmd, NULL);
if (cmd && strlen (cmd))
mm_serial_port_queue_command (port, cmd, 5, disable_done, user_data);
mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), cmd, 5, disable_done, user_data);
else
disable_done (port, NULL, NULL, user_data);
disable_done (MM_AT_SERIAL_PORT (port), NULL, NULL, user_data);
g_free (cmd);
}
@@ -695,13 +698,13 @@ disable (MMModem *modem,
MM_MODEM_STATE_REASON_NONE);
if (mm_port_get_connected (MM_PORT (priv->primary)))
mm_serial_port_flash (priv->primary, 1000, disable_flash_done, info);
mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disable_flash_done, info);
else
disable_flash_done (priv->primary, NULL, info);
disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info);
}
static void
get_string_done (MMSerialPort *port,
get_string_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -725,7 +728,7 @@ get_imei (MMModemGsmCard *modem,
MMCallbackInfo *info;
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
mm_serial_port_queue_command_cached (priv->primary, "+CGSN", 3, get_string_done, info);
mm_at_serial_port_queue_command_cached (priv->primary, "+CGSN", 3, get_string_done, info);
}
static void
@@ -737,7 +740,7 @@ get_imsi (MMModemGsmCard *modem,
MMCallbackInfo *info;
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
mm_serial_port_queue_command_cached (priv->primary, "+CIMI", 3, get_string_done, info);
mm_at_serial_port_queue_command_cached (priv->primary, "+CIMI", 3, get_string_done, info);
}
static void
@@ -768,7 +771,7 @@ strip_tag (const char *str, const char *tag)
}
static void
get_version_done (MMSerialPort *port,
get_version_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -785,7 +788,7 @@ get_version_done (MMSerialPort *port,
}
static void
get_model_done (MMSerialPort *port,
get_model_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -800,7 +803,7 @@ get_model_done (MMSerialPort *port,
}
static void
get_manufacturer_done (MMSerialPort *port,
get_manufacturer_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -827,9 +830,9 @@ get_card_info (MMModem *modem,
G_CALLBACK (callback),
user_data);
mm_serial_port_queue_command_cached (priv->primary, "+CGMI", 3, get_manufacturer_done, info);
mm_serial_port_queue_command_cached (priv->primary, "+CGMM", 3, get_model_done, info);
mm_serial_port_queue_command_cached (priv->primary, "+CGMR", 3, get_version_done, info);
mm_at_serial_port_queue_command_cached (priv->primary, "+CGMI", 3, get_manufacturer_done, info);
mm_at_serial_port_queue_command_cached (priv->primary, "+CGMM", 3, get_model_done, info);
mm_at_serial_port_queue_command_cached (priv->primary, "+CGMR", 3, get_version_done, info);
}
static void
@@ -841,17 +844,20 @@ pin_puk_recheck_done (MMModem *modem, GError *error, gpointer user_data)
* 'modem' will be NULL.
*/
if (modem) {
MMGenericGsmPrivate *priv;
g_return_if_fail (MM_IS_GENERIC_GSM (modem));
priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
if (close_port)
mm_serial_port_close (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary);
mm_serial_port_close (MM_SERIAL_PORT (priv->primary));
}
}
#define PIN_CLOSE_PORT_TAG "close-port"
static void
send_puk_done (MMSerialPort *port,
send_puk_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -892,11 +898,11 @@ send_puk (MMModemGsmCard *modem,
"Cannot unlock device while connected");
mm_callback_info_schedule (info);
return;
} else if (!mm_serial_port_is_open (priv->primary)) {
} else if (!mm_serial_port_is_open (MM_SERIAL_PORT (priv->primary))) {
/* Modem may not be enabled yet, which sometimes can't be done until
* the device has been unlocked.
*/
if (!mm_serial_port_open (priv->primary, &info->error)) {
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &info->error)) {
mm_callback_info_schedule (info);
return;
}
@@ -906,12 +912,12 @@ send_puk (MMModemGsmCard *modem,
}
command = g_strdup_printf ("+CPIN=\"%s\",\"%s\"", puk, pin);
mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_puk_done, info);
mm_at_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_puk_done, info);
g_free (command);
}
static void
send_pin_done (MMSerialPort *port,
send_pin_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -951,11 +957,11 @@ send_pin (MMModemGsmCard *modem,
"Cannot unlock device while connected");
mm_callback_info_schedule (info);
return;
} else if (!mm_serial_port_is_open (priv->primary)) {
} else if (!mm_serial_port_is_open (MM_SERIAL_PORT (priv->primary))) {
/* Modem may not be enabled yet, which sometimes can't be done until
* the device has been unlocked.
*/
if (!mm_serial_port_open (priv->primary, &info->error)) {
if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &info->error)) {
mm_callback_info_schedule (info);
return;
}
@@ -965,12 +971,12 @@ send_pin (MMModemGsmCard *modem,
}
command = g_strdup_printf ("+CPIN=\"%s\"", pin);
mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_pin_done, info);
mm_at_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_pin_done, info);
g_free (command);
}
static void
enable_pin_done (MMSerialPort *port,
enable_pin_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -995,12 +1001,12 @@ enable_pin (MMModemGsmCard *modem,
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
command = g_strdup_printf ("+CLCK=\"SC\",%d,\"%s\"", enabled ? 1 : 0, pin);
mm_serial_port_queue_command (priv->primary, command, 3, enable_pin_done, info);
mm_at_serial_port_queue_command (priv->primary, command, 3, enable_pin_done, info);
g_free (command);
}
static void
change_pin_done (MMSerialPort *port,
change_pin_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1025,7 +1031,7 @@ change_pin (MMModemGsmCard *modem,
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
command = g_strdup_printf ("+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin);
mm_serial_port_queue_command (priv->primary, command, 3, change_pin_done, info);
mm_at_serial_port_queue_command (priv->primary, command, 3, change_pin_done, info);
g_free (command);
}
@@ -1056,7 +1062,7 @@ parse_operator (const char *reply)
}
static void
read_operator_code_done (MMSerialPort *port,
read_operator_code_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1076,7 +1082,7 @@ read_operator_code_done (MMSerialPort *port,
}
static void
read_operator_name_done (MMSerialPort *port,
read_operator_name_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1186,7 +1192,7 @@ reg_status_updated (MMGenericGsm *self, int new_value, GError **error)
}
static void
reg_state_changed (MMSerialPort *port,
reg_state_changed (MMAtSerialPort *port,
GMatchInfo *match_info,
gpointer user_data)
{
@@ -1236,7 +1242,7 @@ reg_status_again_remove (gpointer data)
}
static void
get_reg_status_done (MMSerialPort *port,
get_reg_status_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1303,17 +1309,17 @@ reg_done:
}
static void
get_registration_status (MMSerialPort *port, MMCallbackInfo *info)
get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info)
{
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
g_warn_if_fail (info == priv->pending_reg_info);
mm_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info);
mm_at_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info);
}
static void
register_done (MMSerialPort *port,
register_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1394,7 +1400,7 @@ do_register (MMModemGsmNetwork *modem,
* the +COPS response is never received.
*/
mm_callback_info_ref (info);
mm_serial_port_queue_command (priv->primary, command, 120, register_done, info);
mm_at_serial_port_queue_command (priv->primary, command, 120, register_done, info);
g_free (command);
}
@@ -1455,7 +1461,7 @@ mm_generic_gsm_connect_complete (MMGenericGsm *modem,
}
static void
connect_report_done (MMSerialPort *port,
connect_report_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1486,7 +1492,7 @@ connect_report_done (MMSerialPort *port,
}
static void
connect_done (MMSerialPort *port,
connect_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1498,7 +1504,7 @@ connect_done (MMSerialPort *port,
info->error = g_error_copy (error);
/* Try to get more information why it failed */
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
mm_serial_port_queue_command (priv->primary, "+CEER", 3, connect_report_done, info);
mm_at_serial_port_queue_command (priv->primary, "+CEER", 3, connect_report_done, info);
} else
mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), NULL, info);
}
@@ -1532,7 +1538,7 @@ connect (MMModem *modem,
} else
command = g_strconcat ("DT", number, NULL);
mm_serial_port_queue_command (priv->primary, command, 60, connect_done, info);
mm_at_serial_port_queue_command (priv->primary, command, 60, connect_done, info);
g_free (command);
}
@@ -1586,7 +1592,7 @@ disconnect (MMModem *modem,
NULL);
mm_modem_set_state (modem, MM_MODEM_STATE_DISCONNECTING, MM_MODEM_STATE_REASON_NONE);
mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info);
mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disconnect_flash_done, info);
}
static void
@@ -1601,7 +1607,7 @@ gsm_network_scan_invoke (MMCallbackInfo *info)
}
static void
scan_done (MMSerialPort *port,
scan_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1633,13 +1639,13 @@ scan (MMModemGsmNetwork *modem,
G_CALLBACK (callback),
user_data);
mm_serial_port_queue_command (priv->primary, "+COPS=?", 120, scan_done, info);
mm_at_serial_port_queue_command (priv->primary, "+COPS=?", 120, scan_done, info);
}
/* SetApn */
static void
set_apn_done (MMSerialPort *port,
set_apn_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1656,7 +1662,7 @@ set_apn_done (MMSerialPort *port,
}
static void
cid_range_read (MMSerialPort *port,
cid_range_read (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1716,13 +1722,13 @@ cid_range_read (MMSerialPort *port,
mm_callback_info_set_data (info, "cid", GUINT_TO_POINTER (cid), NULL);
command = g_strdup_printf ("+CGDCONT=%d,\"IP\",\"%s\"", cid, apn);
mm_serial_port_queue_command (port, command, 3, set_apn_done, info);
mm_at_serial_port_queue_command (port, command, 3, set_apn_done, info);
g_free (command);
}
}
static void
existing_apns_read (MMSerialPort *port,
existing_apns_read (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1787,7 +1793,7 @@ existing_apns_read (MMSerialPort *port,
mm_callback_info_schedule (info);
else
/* APN not configured on the card. Get the allowed CID range */
mm_serial_port_queue_command_cached (port, "+CGDCONT=?", 3, cid_range_read, info);
mm_at_serial_port_queue_command_cached (port, "+CGDCONT=?", 3, cid_range_read, info);
}
static void
@@ -1803,13 +1809,13 @@ set_apn (MMModemGsmNetwork *modem,
mm_callback_info_set_data (info, "apn", g_strdup (apn), g_free);
/* Start by searching if the APN is already in card */
mm_serial_port_queue_command (priv->primary, "+CGDCONT?", 3, existing_apns_read, info);
mm_at_serial_port_queue_command (priv->primary, "+CGDCONT?", 3, existing_apns_read, info);
}
/* GetSignalQuality */
static void
get_signal_quality_done (MMSerialPort *port,
get_signal_quality_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1866,14 +1872,14 @@ get_signal_quality (MMModemGsmNetwork *modem,
}
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, "+CSQ", 3, get_signal_quality_done, info);
mm_at_serial_port_queue_command (connected ? priv->secondary : priv->primary, "+CSQ", 3, get_signal_quality_done, info);
}
/*****************************************************************************/
/* MMModemGsmSms interface */
static void
sms_send_done (MMSerialPort *port,
sms_send_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -1900,7 +1906,7 @@ sms_send (MMModemGsmSms *modem,
MMCallbackInfo *info;
char *command;
gboolean connected;
MMSerialPort *port = NULL;
MMAtSerialPort *port = NULL;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
@@ -1919,16 +1925,16 @@ sms_send (MMModemGsmSms *modem,
}
/* FIXME: use the PDU mode instead */
mm_serial_port_queue_command (port, "AT+CMGF=1", 3, NULL, NULL);
mm_at_serial_port_queue_command (port, "AT+CMGF=1", 3, NULL, NULL);
command = g_strdup_printf ("+CMGS=\"%s\"\r%s\x1a", number, text);
mm_serial_port_queue_command (port, command, 10, sms_send_done, info);
mm_at_serial_port_queue_command (port, command, 10, sms_send_done, info);
g_free (command);
}
MMSerialPort *
mm_generic_gsm_get_port (MMGenericGsm *modem,
MMPortType ptype)
MMAtSerialPort *
mm_generic_gsm_get_at_port (MMGenericGsm *modem,
MMPortType ptype)
{
g_return_val_if_fail (MM_IS_GENERIC_GSM (modem), NULL);
g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL);
+3 -3
View File
@@ -20,7 +20,7 @@
#include "mm-modem-gsm.h"
#include "mm-modem-gsm-network.h"
#include "mm-modem-base.h"
#include "mm-serial-port.h"
#include "mm-at-serial-port.h"
#include "mm-callback-info.h"
#define MM_TYPE_GENERIC_GSM (mm_generic_gsm_get_type ())
@@ -90,8 +90,8 @@ void mm_generic_gsm_check_pin (MMGenericGsm *modem,
MMModemFn callback,
gpointer user_data);
MMSerialPort *mm_generic_gsm_get_port (MMGenericGsm *modem,
MMPortType ptype);
MMAtSerialPort *mm_generic_gsm_get_at_port (MMGenericGsm *modem,
MMPortType ptype);
MMPort *mm_generic_gsm_grab_port (MMGenericGsm *modem,
const char *subsys,
+2 -2
View File
@@ -21,7 +21,7 @@
#include "mm-modem-base.h"
#include "mm-modem.h"
#include "mm-serial-port.h"
#include "mm-at-serial-port.h"
#include "mm-errors.h"
#include "mm-options.h"
#include "mm-properties-changed-signal.h"
@@ -113,7 +113,7 @@ mm_modem_base_add_port (MMModemBase *self,
}
if (!strcmp (subsys, "tty"))
port = MM_PORT (mm_serial_port_new (name, ptype));
port = MM_PORT (mm_at_serial_port_new (name, ptype));
else if (!strcmp (subsys, "net")) {
port = MM_PORT (g_object_new (MM_TYPE_PORT,
MM_PORT_DEVICE, name,
+27 -27
View File
@@ -26,7 +26,7 @@
#include <gudev/gudev.h>
#include "mm-plugin-base.h"
#include "mm-serial-port.h"
#include "mm-at-serial-port.h"
#include "mm-serial-parsers.h"
#include "mm-errors.h"
#include "mm-marshal.h"
@@ -92,7 +92,7 @@ typedef struct {
guint open_id;
guint32 open_tries;
MMSerialPort *probe_port;
MMAtSerialPort *probe_port;
guint32 probed_caps;
ProbeState probe_state;
guint probe_id;
@@ -378,7 +378,7 @@ probe_complete (MMPluginBaseSupportsTask *task)
}
static void
parse_response (MMSerialPort *port,
parse_response (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data);
@@ -391,7 +391,7 @@ real_handle_probe_response (MMPluginBase *self,
const GError *error)
{
MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
MMSerialPort *port = task_priv->probe_port;
MMAtSerialPort *port = task_priv->probe_port;
gboolean ignore_error = FALSE;
/* Some modems (Huawei E160g) won't respond to +GCAP with no SIM, but
@@ -405,7 +405,7 @@ real_handle_probe_response (MMPluginBase *self,
/* Try GCAP again */
if (task_priv->probe_state < PROBE_STATE_GCAP_TRY3) {
task_priv->probe_state++;
mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, task);
mm_at_serial_port_queue_command (port, "+GCAP", 3, parse_response, task);
} else {
/* Otherwise, if all the GCAP tries timed out, ignore the port
* as it's probably not an AT-capable port.
@@ -459,19 +459,19 @@ real_handle_probe_response (MMPluginBase *self,
switch (task_priv->probe_state) {
case PROBE_STATE_GCAP_TRY2:
case PROBE_STATE_GCAP_TRY3:
mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, task);
mm_at_serial_port_queue_command (port, "+GCAP", 3, parse_response, task);
break;
case PROBE_STATE_ATI:
/* After the last GCAP attempt, try ATI */
mm_serial_port_queue_command (port, "I", 3, parse_response, task);
mm_at_serial_port_queue_command (port, "I", 3, parse_response, task);
break;
case PROBE_STATE_CPIN:
/* After the ATI attempt, try CPIN */
mm_serial_port_queue_command (port, "+CPIN?", 3, parse_response, task);
mm_at_serial_port_queue_command (port, "+CPIN?", 3, parse_response, task);
break;
case PROBE_STATE_CGMM:
/* After the CPIN attempt, try CGMM */
mm_serial_port_queue_command (port, "+CGMM", 3, parse_response, task);
mm_at_serial_port_queue_command (port, "+CGMM", 3, parse_response, task);
break;
default:
/* Probably not GSM or CDMA */
@@ -515,7 +515,7 @@ handle_probe_response (gpointer user_data)
}
static void
parse_response (MMSerialPort *port,
parse_response (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -545,7 +545,7 @@ parse_response (MMSerialPort *port,
static void flash_done (MMSerialPort *port, GError *error, gpointer user_data);
static void
custom_init_response (MMSerialPort *port,
custom_init_response (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
@@ -557,7 +557,7 @@ custom_init_response (MMSerialPort *port,
task_priv->custom_init_tries++;
if (task_priv->custom_init_tries < task_priv->custom_init_max_tries) {
/* Try the custom command again */
flash_done (port, NULL, user_data);
flash_done (MM_SERIAL_PORT (port), NULL, user_data);
return;
} else if (task_priv->custom_init_fail_if_timeout) {
/* Fail the probe if the plugin wanted it and the command timed out */
@@ -569,7 +569,7 @@ custom_init_response (MMSerialPort *port,
}
/* Otherwise proceed to probing */
mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, user_data);
mm_at_serial_port_queue_command (port, "+GCAP", 3, parse_response, user_data);
}
static void
@@ -583,14 +583,14 @@ flash_done (MMSerialPort *port, GError *error, gpointer user_data)
if (task_priv->custom_init) {
if (!delay_secs)
delay_secs = 3;
mm_serial_port_queue_command (port,
task_priv->custom_init,
delay_secs,
custom_init_response,
user_data);
mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port),
task_priv->custom_init,
delay_secs,
custom_init_response,
user_data);
} else {
/* Otherwise start normal probing */
custom_init_response (port, NULL, NULL, user_data);
custom_init_response (MM_AT_SERIAL_PORT (port), NULL, NULL, user_data);
}
}
@@ -603,7 +603,7 @@ try_open (gpointer user_data)
task_priv->open_id = 0;
if (!mm_serial_port_open (task_priv->probe_port, &error)) {
if (!mm_serial_port_open (MM_SERIAL_PORT (task_priv->probe_port), &error)) {
if (++task_priv->open_tries > 4) {
/* took too long to open the port; give up */
g_warning ("(%s): failed to open after 4 tries.",
@@ -629,7 +629,7 @@ try_open (gpointer user_data)
g_debug ("(%s): probe requested by plugin '%s'",
g_udev_device_get_name (port),
mm_plugin_get_name (MM_PLUGIN (task_priv->plugin)));
mm_serial_port_flash (task_priv->probe_port, 100, flash_done, task);
mm_serial_port_flash (MM_SERIAL_PORT (task_priv->probe_port), 100, flash_done, task);
}
return FALSE;
@@ -641,7 +641,7 @@ mm_plugin_base_probe_port (MMPluginBase *self,
GError **error)
{
MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
MMSerialPort *serial;
MMAtSerialPort *serial;
const char *name;
GUdevDevice *port;
@@ -654,7 +654,7 @@ mm_plugin_base_probe_port (MMPluginBase *self,
name = g_udev_device_get_name (port);
g_assert (name);
serial = mm_serial_port_new (name, MM_PORT_TYPE_PRIMARY);
serial = mm_at_serial_port_new (name, MM_PORT_TYPE_PRIMARY);
if (serial == NULL) {
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Failed to create new serial port.");
@@ -666,10 +666,10 @@ mm_plugin_base_probe_port (MMPluginBase *self,
MM_PORT_CARRIER_DETECT, FALSE,
NULL);
mm_serial_port_set_response_parser (serial,
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
mm_at_serial_port_set_response_parser (serial,
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
/* Open the port */
task_priv->probe_port = serial;
+137 -196
View File
@@ -55,16 +55,7 @@ typedef struct {
GHashTable *reply_cache;
GIOChannel *channel;
GQueue *queue;
GString *command;
GString *response;
gboolean connected;
/* Response parser data */
MMSerialResponseParserFn response_parser_fn;
gpointer response_parser_user_data;
GDestroyNotify response_parser_notify;
GSList *unsolicited_msg_handlers;
GByteArray *response;
struct termios old_t;
@@ -165,33 +156,6 @@ mm_serial_port_print_config (MMSerialPort *port, const char *detail)
}
#endif
typedef struct {
GRegex *regex;
MMSerialUnsolicitedMsgFn callback;
gpointer user_data;
GDestroyNotify notify;
} MMUnsolicitedMsgHandler;
static void
mm_serial_port_set_cached_reply (MMSerialPort *self,
const char *command,
const char *reply)
{
if (reply)
g_hash_table_insert (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache,
g_strdup (command),
g_strdup (reply));
else
g_hash_table_remove (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command);
}
static const char *
mm_serial_port_get_cached_reply (MMSerialPort *self,
const char *command)
{
return (char *) g_hash_table_lookup (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command);
}
static int
parse_baudrate (guint i)
{
@@ -411,13 +375,13 @@ serial_debug (MMSerialPort *self, const char *prefix, const char *buf, int len)
static gboolean
mm_serial_port_send_command (MMSerialPort *self,
const char *command,
GByteArray *command,
GError **error)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
const char *s;
int status;
int status, i = 0;
int eagain_count = 1000;
const guint8 *p;
if (priv->fd < 0) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED,
@@ -431,21 +395,15 @@ mm_serial_port_send_command (MMSerialPort *self,
return FALSE;
}
g_string_truncate (priv->command, g_str_has_prefix (command, "AT") ? 0 : 2);
g_string_append (priv->command, command);
if (command[strlen (command)] != '\r')
g_string_append_c (priv->command, '\r');
serial_debug (self, "-->", priv->command->str, -1);
serial_debug (self, "-->", (const char *) command->data, command->len);
/* Only accept about 3 seconds of EAGAIN */
if (priv->send_delay > 0)
eagain_count = 3000000 / priv->send_delay;
s = priv->command->str;
while (*s) {
status = write (priv->fd, s, 1);
while (i < command->len) {
p = &command->data[i];
status = write (priv->fd, p, 1);
if (status < 0) {
if (errno == EAGAIN) {
eagain_count--;
@@ -460,18 +418,46 @@ mm_serial_port_send_command (MMSerialPort *self,
break;
}
} else
s++;
i++;
if (priv->send_delay)
usleep (priv->send_delay);
}
return *s == '\0';
return i == command->len;
}
static void
mm_serial_port_set_cached_reply (MMSerialPort *self,
const GByteArray *command,
const GByteArray *response)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
g_return_if_fail (self != NULL);
g_return_if_fail (MM_IS_SERIAL_PORT (self));
g_return_if_fail (command != NULL);
if (response) {
GByteArray *cmd_copy = g_byte_array_sized_new (command->len);
GByteArray *rsp_copy = g_byte_array_sized_new (response->len);
g_byte_array_append (cmd_copy, command->data, command->len);
g_byte_array_append (rsp_copy, response->data, response->len);
g_hash_table_insert (priv->reply_cache, cmd_copy, rsp_copy);
} else
g_hash_table_remove (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command);
}
static const GByteArray *
mm_serial_port_get_cached_reply (MMSerialPort *self, GByteArray *command)
{
return (const GByteArray *) g_hash_table_lookup (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command);
}
typedef struct {
char *command;
MMSerialResponseFn callback;
GByteArray *command;
GCallback callback;
gpointer user_data;
guint32 timeout;
gboolean cached;
@@ -514,19 +500,24 @@ mm_serial_port_got_response (MMSerialPort *self, GError *error)
info = (MMQueueData *) g_queue_pop_head (priv->queue);
if (info) {
if (info->cached && !error)
mm_serial_port_set_cached_reply (self, info->command, priv->response->str);
mm_serial_port_set_cached_reply (self, info->command, priv->response);
if (info->callback)
info->callback (self, priv->response, error, info->user_data);
g_warn_if_fail (MM_SERIAL_PORT_GET_CLASS (self)->handle_response != NULL);
MM_SERIAL_PORT_GET_CLASS (self)->handle_response (self,
priv->response,
error,
info->callback,
info->user_data);
g_free (info->command);
g_byte_array_free (info->command, TRUE);
g_slice_free (MMQueueData, info);
}
if (error)
g_error_free (error);
g_string_truncate (priv->response, 0);
if (priv->response->len)
g_byte_array_remove_range (priv->response, 0, priv->response->len);
if (!g_queue_is_empty (priv->queue))
mm_serial_port_schedule_queue_process (self);
}
@@ -566,10 +557,10 @@ mm_serial_port_queue_process (gpointer data)
return FALSE;
if (info->cached) {
const char *cached = mm_serial_port_get_cached_reply (self, info->command);
const GByteArray *cached = mm_serial_port_get_cached_reply (self, info->command);
if (cached) {
g_string_append (priv->response, cached);
g_byte_array_append (priv->response, cached->data, cached->len);
mm_serial_port_got_response (self, NULL);
return FALSE;
}
@@ -590,111 +581,16 @@ mm_serial_port_queue_process (gpointer data)
return FALSE;
}
void
mm_serial_port_add_unsolicited_msg_handler (MMSerialPort *self,
GRegex *regex,
MMSerialUnsolicitedMsgFn callback,
gpointer user_data,
GDestroyNotify notify)
{
MMUnsolicitedMsgHandler *handler;
MMSerialPortPrivate *priv;
g_return_if_fail (MM_IS_SERIAL_PORT (self));
g_return_if_fail (regex != NULL);
handler = g_slice_new (MMUnsolicitedMsgHandler);
handler->regex = g_regex_ref (regex);
handler->callback = callback;
handler->user_data = user_data;
handler->notify = notify;
priv = MM_SERIAL_PORT_GET_PRIVATE (self);
priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler);
}
void
mm_serial_port_set_response_parser (MMSerialPort *self,
MMSerialResponseParserFn fn,
gpointer user_data,
GDestroyNotify notify)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
g_return_if_fail (MM_IS_SERIAL_PORT (self));
if (priv->response_parser_notify)
priv->response_parser_notify (priv->response_parser_user_data);
priv->response_parser_fn = fn;
priv->response_parser_user_data = user_data;
priv->response_parser_notify = notify;
}
static gboolean
remove_eval_cb (const GMatchInfo *match_info,
GString *result,
gpointer user_data)
{
int *result_len = (int *) user_data;
int start;
int end;
if (g_match_info_fetch_pos (match_info, 0, &start, &end))
*result_len -= (end - start);
return FALSE;
}
static void
parse_unsolicited_messages (MMSerialPort *self,
GString *response)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
GSList *iter;
for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) {
MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) iter->data;
GMatchInfo *match_info;
gboolean matches;
matches = g_regex_match_full (handler->regex, response->str, response->len, 0, 0, &match_info, NULL);
if (handler->callback) {
while (g_match_info_matches (match_info)) {
handler->callback (self, match_info, handler->user_data);
g_match_info_next (match_info, NULL);
}
}
g_match_info_free (match_info);
if (matches) {
/* Remove matches */
char *str;
int result_len = response->len;
str = g_regex_replace_eval (handler->regex, response->str, response->len, 0, 0,
remove_eval_cb, &result_len, NULL);
g_string_truncate (response, 0);
g_string_append_len (response, str, result_len);
g_free (str);
}
}
}
static gboolean
parse_response (MMSerialPort *self,
GString *response,
GByteArray *response,
GError **error)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
if (MM_SERIAL_PORT_GET_CLASS (self)->parse_unsolicited)
MM_SERIAL_PORT_GET_CLASS (self)->parse_unsolicited (self, response);
g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE);
parse_unsolicited_messages (self, response);
return priv->response_parser_fn (priv->response_parser_user_data, response, error);
g_return_val_if_fail (MM_SERIAL_PORT_GET_CLASS (self)->parse_response, FALSE);
return MM_SERIAL_PORT_GET_CLASS (self)->parse_response (self, response, error);
}
static gboolean
@@ -709,13 +605,15 @@ data_available (GIOChannel *source,
GIOStatus status;
if (condition & G_IO_HUP) {
g_string_truncate (priv->response, 0);
if (priv->response->len)
g_byte_array_remove_range (priv->response, 0, priv->response->len);
mm_serial_port_close (self);
return FALSE;
}
if (condition & G_IO_ERR) {
g_string_truncate (priv->response, 0);
if (priv->response->len)
g_byte_array_remove_range (priv->response, 0, priv->response->len);
return TRUE;
}
@@ -735,14 +633,14 @@ data_available (GIOChannel *source,
if (bytes_read > 0) {
serial_debug (self, "<--", buf, bytes_read);
g_string_append_len (priv->response, buf, bytes_read);
g_byte_array_append (priv->response, (const guint8 *) buf, bytes_read);
}
/* Make sure the string doesn't grow too long */
/* Make sure the response doesn't grow too long */
if (priv->response->len > SERIAL_BUF_SIZE) {
g_warning ("%s (%s): response buffer filled before repsonse received",
G_STRFUNC, mm_port_get_device (MM_PORT (self)));
g_string_erase (priv->response, 0, (SERIAL_BUF_SIZE / 2));
g_byte_array_remove_range (priv->response, 0, (SERIAL_BUF_SIZE / 2));
}
if (parse_response (self, priv->response, &err))
@@ -865,6 +763,7 @@ void
mm_serial_port_close (MMSerialPort *self)
{
MMSerialPortPrivate *priv;
int i;
g_return_if_fail (MM_IS_SERIAL_PORT (self));
@@ -896,14 +795,24 @@ mm_serial_port_close (MMSerialPort *self)
close (priv->fd);
priv->fd = -1;
}
/* Clear the command queue */
for (i = 0; i < g_queue_get_length (priv->queue); i++) {
MMQueueData *item = g_queue_peek_nth (priv->queue, i);
g_byte_array_free (item->command, TRUE);
g_slice_free (MMQueueData, item);
}
g_queue_clear (priv->queue);
}
static void
internal_queue_command (MMSerialPort *self,
const char *command,
GByteArray *command,
gboolean take_command,
gboolean cached,
guint32 timeout_seconds,
MMSerialResponseFn callback,
GCallback callback,
gpointer user_data)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
@@ -913,7 +822,12 @@ internal_queue_command (MMSerialPort *self,
g_return_if_fail (command != NULL);
info = g_slice_new0 (MMQueueData);
info->command = g_strdup (command);
if (take_command)
info->command = command;
else {
info->command = g_byte_array_sized_new (command->len);
g_byte_array_append (info->command, command->data, command->len);
}
info->cached = cached;
info->timeout = timeout_seconds;
info->callback = callback;
@@ -921,7 +835,7 @@ internal_queue_command (MMSerialPort *self,
/* Clear the cached value for this command if not asking for cached value */
if (!cached)
mm_serial_port_set_cached_reply (self, command, NULL);
mm_serial_port_set_cached_reply (self, info->command, NULL);
g_queue_push_tail (priv->queue, info);
@@ -931,22 +845,24 @@ internal_queue_command (MMSerialPort *self,
void
mm_serial_port_queue_command (MMSerialPort *self,
const char *command,
GByteArray *command,
gboolean take_command,
guint32 timeout_seconds,
MMSerialResponseFn callback,
GCallback callback,
gpointer user_data)
{
internal_queue_command (self, command, FALSE, timeout_seconds, callback, user_data);
internal_queue_command (self, command, take_command, FALSE, timeout_seconds, callback, user_data);
}
void
mm_serial_port_queue_command_cached (MMSerialPort *self,
const char *command,
GByteArray *command,
gboolean take_command,
guint32 timeout_seconds,
MMSerialResponseFn callback,
GCallback callback,
gpointer user_data)
{
internal_queue_command (self, command, TRUE, timeout_seconds, callback, user_data);
internal_queue_command (self, command, take_command, TRUE, timeout_seconds, callback, user_data);
}
typedef struct {
@@ -1122,12 +1038,54 @@ mm_serial_port_new (const char *name, MMPortType ptype)
NULL));
}
static gboolean
ba_equal (gconstpointer v1, gconstpointer v2)
{
const GByteArray *a = v1;
const GByteArray *b = v2;
if (!a && b)
return -1;
else if (a && !b)
return 1;
else if (!a && !b)
return 0;
g_assert (a && b);
if (a->len < b->len)
return -1;
else if (a->len > b->len)
return 1;
g_assert (a->len == b->len);
return !memcmp (a->data, b->data, a->len);
}
static guint
ba_hash (gconstpointer v)
{
/* 31 bit hash function */
const GByteArray *array = v;
guint32 i, h = (const signed char) array->data[0];
for (i = 1; i < array->len; i++)
h = (h << 5) - h + (const signed char) array->data[i];
return h;
}
static void
ba_free (gpointer v)
{
g_byte_array_free ((GByteArray *) v, TRUE);
}
static void
mm_serial_port_init (MMSerialPort *self)
{
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
priv->reply_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
priv->reply_cache = g_hash_table_new_full (ba_hash, ba_equal, ba_free, ba_free);
priv->fd = -1;
priv->baud = 57600;
@@ -1137,8 +1095,7 @@ mm_serial_port_init (MMSerialPort *self)
priv->send_delay = 1000;
priv->queue = g_queue_new ();
priv->command = g_string_new_len ("AT", SERIAL_BUF_SIZE);
priv->response = g_string_sized_new (SERIAL_BUF_SIZE);
priv->response = g_byte_array_sized_new (500);
}
static void
@@ -1212,24 +1169,8 @@ finalize (GObject *object)
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
g_hash_table_destroy (priv->reply_cache);
g_byte_array_free (priv->response, TRUE);
g_queue_free (priv->queue);
g_string_free (priv->command, TRUE);
g_string_free (priv->response, TRUE);
while (priv->unsolicited_msg_handlers) {
MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) priv->unsolicited_msg_handlers->data;
if (handler->notify)
handler->notify (handler->user_data);
g_regex_unref (handler->regex);
g_slice_free (MMUnsolicitedMsgHandler, handler);
priv->unsolicited_msg_handlers = g_slist_delete_link (priv->unsolicited_msg_handlers,
priv->unsolicited_msg_handlers);
}
if (priv->response_parser_notify)
priv->response_parser_notify (priv->response_parser_user_data);
G_OBJECT_CLASS (mm_serial_port_parent_class)->finalize (object);
}
+40 -35
View File
@@ -39,19 +39,6 @@
typedef struct _MMSerialPort MMSerialPort;
typedef struct _MMSerialPortClass MMSerialPortClass;
typedef gboolean (*MMSerialResponseParserFn) (gpointer user_data,
GString *response,
GError **error);
typedef void (*MMSerialUnsolicitedMsgFn) (MMSerialPort *port,
GMatchInfo *match_info,
gpointer user_data);
typedef void (*MMSerialResponseFn) (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data);
typedef void (*MMSerialFlashFn) (MMSerialPort *port,
GError *error,
gpointer user_data);
@@ -62,40 +49,44 @@ struct _MMSerialPort {
struct _MMSerialPortClass {
MMPortClass parent;
/* Called for subclasses to parse unsolicited responses. If any recognized
* unsolicited response is found, it should be removed from the 'response'
* byte array before returning.
*/
void (*parse_unsolicited) (MMSerialPort *self, GByteArray *response);
/* Called to parse the device's response to a command or determine if the
* response was an error response. If the response indicates an error, an
* appropriate error should be returned in the 'error' argument. The
* function should return FALSE if there is not enough data yet to determine
* the device's reply (whether success *or* error), and should return TRUE
* when the device's response has been recognized and parsed.
*/
gboolean (*parse_response) (MMSerialPort *self,
GByteArray *response,
GError **error);
/* Called after parsing to allow the command response to be delivered to
* it's callback to be handled.
*/
void (*handle_response) (MMSerialPort *self,
GByteArray *response,
GError *error,
GCallback callback,
gpointer callback_data);
};
GType mm_serial_port_get_type (void);
MMSerialPort *mm_serial_port_new (const char *name, MMPortType ptype);
void mm_serial_port_add_unsolicited_msg_handler (MMSerialPort *self,
GRegex *regex,
MMSerialUnsolicitedMsgFn callback,
gpointer user_data,
GDestroyNotify notify);
void mm_serial_port_set_response_parser (MMSerialPort *self,
MMSerialResponseParserFn fn,
gpointer user_data,
GDestroyNotify notify);
gboolean mm_serial_port_is_open (MMSerialPort *self);
gboolean mm_serial_port_open (MMSerialPort *self,
GError **error);
void mm_serial_port_close (MMSerialPort *self);
void mm_serial_port_queue_command (MMSerialPort *self,
const char *command,
guint32 timeout_seconds,
MMSerialResponseFn callback,
gpointer user_data);
void mm_serial_port_queue_command_cached (MMSerialPort *self,
const char *command,
guint32 timeout_seconds,
MMSerialResponseFn callback,
gpointer user_data);
gboolean mm_serial_port_flash (MMSerialPort *self,
guint32 flash_time,
@@ -103,5 +94,19 @@ gboolean mm_serial_port_flash (MMSerialPort *self,
gpointer user_data);
void mm_serial_port_flash_cancel (MMSerialPort *self);
void mm_serial_port_queue_command (MMSerialPort *self,
GByteArray *command,
gboolean take_command,
guint32 timeout_seconds,
GCallback callback,
gpointer user_data);
void mm_serial_port_queue_command_cached (MMSerialPort *self,
GByteArray *command,
gboolean take_command,
guint32 timeout_seconds,
GCallback callback,
gpointer user_data);
#endif /* MM_SERIAL_PORT_H */