aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-errors.c1
-rw-r--r--src/mm-errors.h3
-rw-r--r--src/mm-generic-cdma.c46
-rw-r--r--src/mm-generic-gsm.c22
-rw-r--r--src/mm-port.c40
-rw-r--r--src/mm-port.h5
-rw-r--r--src/mm-serial-port.c47
-rw-r--r--src/mm-serial-port.h2
8 files changed, 136 insertions, 30 deletions
diff --git a/src/mm-errors.c b/src/mm-errors.c
index e313f0f4..f0b11566 100644
--- a/src/mm-errors.c
+++ b/src/mm-errors.c
@@ -54,6 +54,7 @@ mm_modem_error_get_type (void)
static const GEnumValue values[] = {
ENUM_ENTRY (MM_MODEM_ERROR_GENERAL, "General"),
ENUM_ENTRY (MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, "OperationNotSupported"),
+ ENUM_ENTRY (MM_MODEM_ERROR_CONNECTED, "Connected"),
{ 0, 0, 0 }
};
diff --git a/src/mm-errors.h b/src/mm-errors.h
index e9fa3ace..0e9e0d4c 100644
--- a/src/mm-errors.h
+++ b/src/mm-errors.h
@@ -20,7 +20,8 @@ GType mm_serial_error_get_type (void);
enum {
MM_MODEM_ERROR_GENERAL = 0,
- MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED = 1
+ MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED = 1,
+ MM_MODEM_ERROR_CONNECTED = 2
};
#define MM_MODEM_ERROR (mm_modem_error_quark ())
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c
index 5d58a81f..b5e10fd6 100644
--- a/src/mm-generic-cdma.c
+++ b/src/mm-generic-cdma.c
@@ -20,6 +20,7 @@ typedef struct {
char *plugin;
char *device;
+ guint32 signal_quality;
guint32 ip_method;
gboolean valid;
@@ -238,10 +239,15 @@ dial_done (MMSerialPort *port,
GError *error,
gpointer user_data)
{
+ MMGenericCdmaPrivate *priv;
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
if (error)
info->error = g_error_copy (error);
+ else {
+ priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
+ mm_port_set_connected (priv->data, TRUE);
+ }
mm_callback_info_schedule (info);
}
@@ -265,7 +271,12 @@ connect (MMModem *modem,
static void
disconnect_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_callback_info_schedule ((MMCallbackInfo *) user_data);
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMGenericCdmaPrivate *priv;
+
+ priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
+ mm_port_set_connected (priv->data, FALSE);
+ mm_callback_info_schedule (info);
}
static void
@@ -370,6 +381,7 @@ get_signal_quality_done (MMSerialPort *port,
GError *error,
gpointer user_data)
{
+ MMGenericCdmaPrivate *priv;
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
char *reply = response->str;
@@ -391,6 +403,8 @@ get_signal_quality_done (MMSerialPort *port,
/* Normalize the quality */
quality = CLAMP (quality, 0, 31) * 100 / 31;
+ priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
+ priv->signal_quality = quality;
mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL);
}
} else
@@ -408,6 +422,14 @@ get_signal_quality (MMModemCdma *modem,
{
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
+ gboolean connected;
+
+ connected = mm_port_get_connected (MM_PORT (priv->primary));
+ if (connected && !priv->secondary) {
+ g_message ("Returning saved signal quality %d", priv->signal_quality);
+ callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data);
+ return;
+ }
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
/* Prefer secondary port for signal strength */
@@ -443,6 +465,17 @@ get_esn (MMModemCdma *modem,
{
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
+ gboolean connected;
+ GError *error;
+
+ connected = mm_port_get_connected (MM_PORT (priv->primary));
+ if (connected && !priv->secondary) {
+ error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_CONNECTED,
+ "Cannot get ESN while connected");
+ callback (MM_MODEM (modem), NULL, error, user_data);
+ g_error_free (error);
+ return;
+ }
info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data);
mm_serial_port_queue_command_cached (priv->primary, "+GSN", 3, get_string_done, info);
@@ -522,6 +555,17 @@ get_serving_system (MMModemCdma *modem,
{
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem);
MMCallbackInfo *info;
+ gboolean connected;
+ GError *error;
+
+ connected = mm_port_get_connected (MM_PORT (priv->primary));
+ if (connected && !priv->secondary) {
+ error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_CONNECTED,
+ "Cannot get serving system while connected");
+ callback (modem, 0, 0, 0, error, user_data);
+ g_error_free (error);
+ return;
+ }
info = mm_callback_info_new_full (MM_MODEM (modem),
serving_system_invoke,
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 8435ee8e..743a2466 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -23,7 +23,6 @@ typedef struct {
gboolean valid;
- char *data_device;
char *oper_code;
char *oper_name;
guint32 ip_method;
@@ -406,7 +405,7 @@ enable (MMModem *modem,
if (!do_enable) {
mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem));
- if (mm_serial_port_is_connected (priv->primary))
+ if (mm_port_get_connected (MM_PORT (priv->primary)))
mm_serial_port_flash (priv->primary, 1000, disable_flash_done, info);
else
disable_flash_done (priv->primary, info);
@@ -976,17 +975,19 @@ connect_done (MMSerialPort *port,
GError *error,
gpointer user_data)
{
- MMGenericGsmPrivate *priv;
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
if (error) {
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);
- } else
+ } else {
/* Done */
+ mm_port_set_connected (priv->data, TRUE);
mm_callback_info_schedule (info);
+ }
}
static void
@@ -1023,7 +1024,11 @@ connect (MMModem *modem,
static void
disconnect_flash_done (MMSerialPort *port, gpointer user_data)
{
- mm_callback_info_schedule ((MMCallbackInfo *) user_data);
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+
+ mm_port_set_connected (priv->data, FALSE);
+ mm_callback_info_schedule (info);
}
static void
@@ -1361,7 +1366,7 @@ get_signal_quality (MMModemGsmNetwork *modem,
MMCallbackInfo *info;
gboolean connected;
- connected = mm_serial_port_is_connected (priv->primary);
+ connected = mm_port_get_connected (MM_PORT (priv->primary));
if (connected && !priv->secondary) {
g_message ("Returning saved signal quality %d", priv->signal_quality);
callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data);
@@ -1408,14 +1413,14 @@ sms_send (MMModemGsmSms *modem,
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
- connected = mm_serial_port_is_connected (priv->primary);
+ connected = mm_port_get_connected (MM_PORT (priv->primary));
if (connected)
port = priv->secondary;
else
port = priv->primary;
if (!port) {
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_CONNECTED,
"Cannot send SMS while connected");
mm_callback_info_schedule (info);
return;
@@ -1827,7 +1832,6 @@ finalize (GObject *object)
mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (object));
g_free (priv->driver);
- g_free (priv->data_device);
g_free (priv->oper_code);
g_free (priv->oper_name);
diff --git a/src/mm-port.c b/src/mm-port.c
index 715db958..7e8edc4f 100644
--- a/src/mm-port.c
+++ b/src/mm-port.c
@@ -28,6 +28,7 @@ enum {
PROP_SUBSYS,
PROP_TYPE,
PROP_CARRIER_DETECT,
+ PROP_CONNECTED,
LAST_PROP
};
@@ -39,6 +40,7 @@ typedef struct {
MMPortSubsys subsys;
MMPortType ptype;
gboolean carrier_detect;
+ gboolean connected;
} MMPortPrivate;
/*****************************************************************************/
@@ -117,6 +119,30 @@ mm_port_get_carrier_detect (MMPort *self)
return MM_PORT_GET_PRIVATE (self)->carrier_detect;
}
+gboolean
+mm_port_get_connected (MMPort *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (MM_IS_PORT (self), FALSE);
+
+ return MM_PORT_GET_PRIVATE (self)->connected;
+}
+
+void
+mm_port_set_connected (MMPort *self, gboolean connected)
+{
+ MMPortPrivate *priv;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (MM_IS_PORT (self));
+
+ priv = MM_PORT_GET_PRIVATE (self);
+ if (priv->connected != connected) {
+ priv->connected = connected;
+ g_object_notify (G_OBJECT (self), MM_PORT_CONNECTED);
+ }
+}
+
/*****************************************************************************/
static void
@@ -146,6 +172,9 @@ set_property (GObject *object, guint prop_id,
case PROP_CARRIER_DETECT:
priv->carrier_detect = g_value_get_boolean (value);
break;
+ case PROP_CONNECTED:
+ priv->connected = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -171,6 +200,9 @@ get_property (GObject *object, guint prop_id,
case PROP_CARRIER_DETECT:
g_value_set_boolean (value, priv->carrier_detect);
break;
+ case PROP_CONNECTED:
+ g_value_set_boolean (value, priv->connected);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -235,4 +267,12 @@ mm_port_class_init (MMPortClass *klass)
"Has Carrier Detect",
TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property
+ (object_class, PROP_CONNECTED,
+ g_param_spec_boolean (MM_PORT_CONNECTED,
+ "Connected",
+ "Is connected for data and not usable for control",
+ FALSE,
+ G_PARAM_READWRITE));
}
diff --git a/src/mm-port.h b/src/mm-port.h
index 339b91ea..b5376180 100644
--- a/src/mm-port.h
+++ b/src/mm-port.h
@@ -48,6 +48,7 @@ typedef enum {
#define MM_PORT_SUBSYS "subsys"
#define MM_PORT_TYPE "type"
#define MM_PORT_CARRIER_DETECT "carrier-detect"
+#define MM_PORT_CONNECTED "connected"
typedef struct _MMPort MMPort;
typedef struct _MMPortClass MMPortClass;
@@ -70,5 +71,9 @@ MMPortType mm_port_get_port_type (MMPort *self);
gboolean mm_port_get_carrier_detect (MMPort *self);
+gboolean mm_port_get_connected (MMPort *self);
+
+void mm_port_set_connected (MMPort *self, gboolean connected);
+
#endif /* MM_PORT_H */
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index 26585e37..5b8b6d52 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -58,6 +58,8 @@ typedef struct {
GString *command;
GString *response;
+ gboolean connected;
+
/* Response parser data */
MMSerialResponseParserFn response_parser_fn;
gpointer response_parser_user_data;
@@ -328,7 +330,7 @@ mm_serial_port_send_command (MMSerialPort *self,
return FALSE;
}
- if (mm_serial_port_is_connected (self)) {
+ if (mm_port_get_connected (MM_PORT (self))) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED,
"%s", "Sending command failed: device is connected");
return FALSE;
@@ -864,26 +866,35 @@ mm_serial_port_flash (MMSerialPort *self,
return id;
}
-gboolean
-mm_serial_port_is_connected (MMSerialPort *self)
-{
- MMSerialPortPrivate *priv;
- int mcs = 0;
-
- g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
-
- priv = MM_SERIAL_PORT_GET_PRIVATE (self);
+/*****************************************************************************/
- if (!mm_port_get_carrier_detect (MM_PORT (self)))
- return FALSE;
+static void
+port_connected (MMSerialPort *self, GParamSpec *pspec, gpointer user_data)
+{
+ MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
+ gboolean connected;
if (priv->fd < 0)
- return FALSE;
-
- if (ioctl (priv->fd, TIOCMGET, &mcs) < 0)
- return FALSE;
+ return;
- return mcs & TIOCM_CAR ? TRUE : FALSE;
+ /* When the port is connected, drop the serial port lock so PPP can do
+ * something with the port. When the port is disconnected, grab the lock
+ * again.
+ */
+ connected = mm_port_get_connected (MM_PORT (self));
+
+ if (ioctl (priv->fd, (connected ? TIOCNXCL : TIOCEXCL)) < 0) {
+ g_warning ("%s: (%s) could not %s serial port lock: (%d) %s",
+ __func__,
+ mm_port_get_device (MM_PORT (self)),
+ connected ? "drop" : "re-acquire",
+ errno,
+ strerror (errno));
+ if (!connected) {
+ // FIXME: do something here, maybe try again in a few seconds or
+ // close the port and error out?
+ }
+ }
}
/*****************************************************************************/
@@ -915,6 +926,8 @@ mm_serial_port_init (MMSerialPort *self)
priv->queue = g_queue_new ();
priv->command = g_string_new_len ("AT", SERIAL_BUF_SIZE);
priv->response = g_string_sized_new (SERIAL_BUF_SIZE);
+
+ g_signal_connect (self, "notify::" MM_PORT_CONNECTED, G_CALLBACK (port_connected), NULL);
}
static void
diff --git a/src/mm-serial-port.h b/src/mm-serial-port.h
index 0f4497a2..a077f94f 100644
--- a/src/mm-serial-port.h
+++ b/src/mm-serial-port.h
@@ -99,7 +99,5 @@ guint mm_serial_port_flash (MMSerialPort *self,
MMSerialFlashFn callback,
gpointer user_data);
-gboolean mm_serial_port_is_connected (MMSerialPort *self);
-
#endif /* MM_SERIAL_PORT_H */