Fix HSO modem plugin.

This commit is contained in:
Tambet Ingo
2008-12-01 12:04:08 +02:00
parent 929c1a8a54
commit 3d84a60ab1
4 changed files with 220 additions and 50 deletions

View File

@@ -9,7 +9,9 @@
#include <dbus/dbus-glib.h>
#include "mm-modem-hso.h"
#include "mm-serial.h"
#include "mm-serial-parsers.h"
#include "mm-errors.h"
#include "mm-util.h"
#include "mm-callback-info.h"
static void impl_hso_authenticate (MMModemHso *self,
@@ -28,7 +30,12 @@ static gpointer mm_modem_hso_parent_class = NULL;
typedef struct {
char *network_device;
gboolean authenticated;
GRegex *connection_enabled_regex;
gpointer std_parser;
/* Pending connection attempt */
MMCallbackInfo *connect_pending_data;
guint connect_pending_id;
} MMModemHsoPrivate;
enum {
@@ -51,6 +58,7 @@ mm_modem_hso_new (const char *serial_device,
return MM_MODEM (g_object_new (MM_TYPE_MODEM_HSO,
MM_SERIAL_DEVICE, serial_device,
MM_SERIAL_SEND_DELAY, (guint64) 10000,
MM_MODEM_DRIVER, driver,
MM_MODEM_HSO_NETWORK_DEVICE, network_device,
NULL));
@@ -70,6 +78,18 @@ hso_enable_done (MMSerial *serial,
mm_callback_info_schedule (info);
}
static guint32
hso_get_cid (MMModemHso *self)
{
guint32 cid;
cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (self));
if (cid == 0)
cid = 1;
return cid;
}
static void
hso_enable (MMModemHso *self,
gboolean enabled,
@@ -81,14 +101,40 @@ hso_enable (MMModemHso *self,
info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
command = g_strdup_printf ("AT_OWANCALL=%d,%d,1",
mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)),
enabled ? 1 : 0);
command = g_strdup_printf ("AT_OWANCALL=%d,%d,1", hso_get_cid (self), enabled ? 1 : 0);
mm_serial_queue_command (MM_SERIAL (self), command, 3, hso_enable_done, info);
g_free (command);
}
static void
connect_pending_done (MMModemHso *self)
{
MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (self);
if (priv->connect_pending_data) {
mm_callback_info_schedule (priv->connect_pending_data);
priv->connect_pending_data = NULL;
}
if (priv->connect_pending_id) {
g_source_remove (priv->connect_pending_id);
priv->connect_pending_id = 0;
}
}
static gboolean
hso_connect_timed_out (gpointer data)
{
MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (data);
priv->connect_pending_data->error = g_error_new_literal (MM_SERIAL_ERROR,
MM_SERIAL_RESPONSE_TIMEOUT,
"Connection timed out");
connect_pending_done (MM_MODEM_HSO (data));
return FALSE;
}
static void
hso_enabled (MMModem *modem,
GError *error,
@@ -96,10 +142,20 @@ hso_enabled (MMModem *modem,
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
if (error)
if (error) {
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
mm_callback_info_schedule (info);
} else {
MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (modem);
GSource *source;
source = g_timeout_source_new_seconds (30);
g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (hso_connect_timed_out), G_OBJECT (modem)));
g_source_attach (source, NULL);
priv->connect_pending_data = info;
priv->connect_pending_id = g_source_get_id (source);
g_source_unref (source);
}
}
static void
@@ -140,19 +196,24 @@ mm_hso_modem_authenticate (MMModemHso *self,
gpointer user_data)
{
MMCallbackInfo *info;
char *command;
g_return_if_fail (MM_IS_MODEM_HSO (self));
g_return_if_fail (callback != NULL);
info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
command = g_strdup_printf ("AT$QCPDPP=%d,1,\"%s\",\"%s\"",
mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)),
password ? password : "",
username ? username : "");
mm_serial_queue_command (MM_SERIAL (self), command, 3, auth_done, info);
g_free (command);
if (username || password) {
char *command;
command = g_strdup_printf ("AT$QCPDPP=%d,1,\"%s\",\"%s\"",
hso_get_cid (self),
password ? password : "",
username ? username : "");
mm_serial_queue_command (MM_SERIAL (self), command, 3, auth_done, info);
g_free (command);
} else
auth_done (MM_SERIAL (self), NULL, NULL, info);
}
static void
@@ -193,13 +254,13 @@ get_ip4_config_done (MMSerial *serial,
if (error) {
info->error = g_error_copy (error);
goto out;
} else if (g_str_has_prefix (response->str, OWANDATA_TAG)) {
} else if (!g_str_has_prefix (response->str, OWANDATA_TAG)) {
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Retrieving failed: invalid response.");
goto out;
}
cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (serial));
cid = hso_get_cid (MM_MODEM_HSO (serial));
dns_array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 2);
items = g_strsplit (response->str + strlen (OWANDATA_TAG), ", ", 0);
@@ -249,7 +310,7 @@ mm_hso_modem_get_ip4_config (MMModemHso *self,
mm_callback_info_set_data (info, "callback", callback, NULL);
mm_callback_info_set_data (info, "user-data", user_data, NULL);
command = g_strdup_printf ("AT_OWANDATA=%d", mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)));
command = g_strdup_printf ("AT_OWANDATA=%d", hso_get_cid (self));
mm_serial_queue_command (MM_SERIAL (self), command, 3, get_ip4_config_done, info);
g_free (command);
}
@@ -257,16 +318,45 @@ mm_hso_modem_get_ip4_config (MMModemHso *self,
/*****************************************************************************/
static void
modem_enable_done (MMModem *modem, GError *error, gpointer user_data)
pin_check_done (MMModem *modem, 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
parent_enable_done (MMModem *modem, GError *error, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
if (error) {
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
} else if (GPOINTER_TO_INT (mm_callback_info_get_data (info, "enable")) == FALSE) {
/* Disable, we're done */
mm_callback_info_schedule (info);
} else {
/* HSO needs manual PIN checking */
mm_generic_gsm_check_pin (MM_GENERIC_GSM (modem), pin_check_done, info);
}
}
static void
modem_enable_done (MMSerial *serial,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMModem *parent_modem_iface;
parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (modem));
parent_modem_iface->enable (modem,
parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (serial));
parent_modem_iface->enable (MM_MODEM (serial),
GPOINTER_TO_INT (mm_callback_info_get_data (info, "enable")),
(MMModemFn) mm_callback_info_get_data (info, "callback"),
mm_callback_info_get_data (info, "user-data"));
parent_enable_done, info);
}
static void
@@ -277,16 +367,25 @@ enable (MMModem *modem,
{
MMCallbackInfo *info;
info = mm_callback_info_new (modem, modem_enable_done, NULL);
info->user_data = info;
info = mm_callback_info_new (modem, callback, user_data);
mm_callback_info_set_data (info, "enable", GINT_TO_POINTER (enable), NULL);
mm_callback_info_set_data (info, "callback", callback, NULL);
mm_callback_info_set_data (info, "user-data", user_data, NULL);
if (enable)
mm_callback_info_schedule (info);
modem_enable_done (MM_SERIAL (modem), NULL, NULL, info);
else
hso_enable (MM_MODEM_HSO (modem), FALSE, modem_enable_done, info);
mm_serial_queue_command (MM_SERIAL (modem), "AT_OWANCALL=1,0,0", 3, modem_enable_done, info);
}
static void
do_connect (MMModem *modem,
const char *number,
MMModemFn callback,
gpointer user_data)
{
MMCallbackInfo *info;
info = mm_callback_info_new (modem, callback, user_data);
mm_callback_info_schedule (info);
}
/*****************************************************************************/
@@ -310,6 +409,12 @@ impl_hso_authenticate (MMModemHso *self,
const char *password,
DBusGMethodInvocation *context)
{
/* DBus doesn't support NULLs */
if (username && strlen (username) == 0)
username = NULL;
if (password && strlen (password) == 0)
password = NULL;
mm_hso_modem_authenticate (self, username, password, impl_hso_auth_done, context);
}
@@ -335,17 +440,47 @@ impl_hso_get_ip4_config (MMModemHso *self,
mm_hso_modem_get_ip4_config (self, impl_hso_ip4_config_done, context);
}
static void
connection_enabled (const char *str, gpointer data)
{
if (str && strlen (str) == 4) {
if (str[3] == '1')
connect_pending_done (MM_MODEM_HSO (data));
if (str[3] == '0')
/* FIXME: disconnected. do something when we have modem status signals */
;
}
}
static gboolean
hso_parse_response (gpointer data, GString *response, GError **error)
{
MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (data);
mm_util_strip_string (response, priv->connection_enabled_regex, connection_enabled, data);
return mm_serial_parser_v1_parse (priv->std_parser, response, error);
}
/*****************************************************************************/
static void
mm_modem_hso_init (MMModemHso *self)
{
MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (self);
priv->connection_enabled_regex = g_regex_new ("_OWANCALL: (\\d, \\d)\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
priv->std_parser = (gpointer) mm_serial_parser_v1_new ();
mm_serial_set_response_parser (MM_SERIAL (self), hso_parse_response, self, NULL);
}
static void
modem_init (MMModem *modem_class)
{
modem_class->enable = enable;
modem_class->connect = do_connect;
}
static GObject*
@@ -410,7 +545,12 @@ finalize (GObject *object)
{
MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (object);
/* Clear the pending connection if necessary */
connect_pending_done (MM_MODEM_HSO (object));
g_free (priv->network_device);
g_regex_unref (priv->connection_enabled_regex);
mm_serial_parser_v1_destroy (priv->std_parser);
G_OBJECT_CLASS (mm_modem_hso_parent_class)->finalize (object);
}
@@ -462,6 +602,8 @@ mm_modem_hso_get_type (void)
modem_hso_type = g_type_register_static (MM_TYPE_GENERIC_GSM, "MMModemHso", &modem_hso_type_info, 0);
g_type_add_interface_static (modem_hso_type, MM_TYPE_MODEM, &modem_iface_info);
dbus_g_object_type_install_info (modem_hso_type, &dbus_glib_mm_modem_gsm_hso_object_info);
}
return modem_hso_type;

View File

@@ -24,31 +24,12 @@ mm_modem_option_new (const char *data_device,
}
static void
check_pin_done (MMSerial *serial,
GString *response,
GError *error,
gpointer user_data)
pin_check_done (MMModem *modem, GError *error, gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
gboolean parsed = FALSE;
if (error)
info->error = g_error_copy (error);
else if (g_str_has_prefix (response->str, "+CPIN: ")) {
const char *str = response->str + 7;
if (g_str_has_prefix (str, "READY"))
parsed = TRUE;
else if (g_str_has_prefix (str, "SIM PIN"))
info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_SIM_PIN);
else if (g_str_has_prefix (str, "SIM PUK"))
info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_SIM_PUK);
}
if (!info->error && !parsed)
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"%s", "Could not parse PIN request results");
mm_callback_info_schedule (info);
}
@@ -66,7 +47,7 @@ parent_enable_done (MMModem *modem, GError *error, gpointer user_data)
/* Now check the PIN explicitly, option doesn't seem to report
that it needs it otherwise */
mm_serial_queue_command (MM_SERIAL (modem), "+CPIN?", 3, check_pin_done, info);
mm_generic_gsm_check_pin (MM_GENERIC_GSM (modem), pin_check_done, info);
return;
}

View File

@@ -85,6 +85,49 @@ mm_generic_gsm_set_operator (MMGenericGsm *modem,
priv->oper_name = g_strdup (name);
}
static void
pin_check_done (MMSerial *serial,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
gboolean parsed = FALSE;
if (error)
info->error = g_error_copy (error);
else if (g_str_has_prefix (response->str, "+CPIN: ")) {
const char *str = response->str + 7;
if (g_str_has_prefix (str, "READY"))
parsed = TRUE;
else if (g_str_has_prefix (str, "SIM PIN"))
info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_SIM_PIN);
else if (g_str_has_prefix (str, "SIM PUK"))
info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_SIM_PUK);
/* FIXME: There's more exotic ones that are not handled right now */
}
if (!info->error && !parsed)
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"%s", "Could not parse PIN request results");
mm_callback_info_schedule (info);
}
void
mm_generic_gsm_check_pin (MMGenericGsm *modem,
MMModemFn callback,
gpointer user_data)
{
MMCallbackInfo *info;
g_return_if_fail (MM_IS_GENERIC_GSM (modem));
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
mm_serial_queue_command (MM_SERIAL (modem), "+CPIN?", 3, pin_check_done, info);
}
/*****************************************************************************/
static void

View File

@@ -37,4 +37,8 @@ void mm_generic_gsm_set_operator (MMGenericGsm *modem,
const char *code,
const char *name);
void mm_generic_gsm_check_pin (MMGenericGsm *modem,
MMModemFn callback,
gpointer user_data);
#endif /* MM_GENERIC_GSM_H */