diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-errors.c | 1 | ||||
-rw-r--r-- | src/mm-errors.h | 3 | ||||
-rw-r--r-- | src/mm-generic-cdma.c | 46 | ||||
-rw-r--r-- | src/mm-generic-gsm.c | 22 | ||||
-rw-r--r-- | src/mm-port.c | 40 | ||||
-rw-r--r-- | src/mm-port.h | 5 | ||||
-rw-r--r-- | src/mm-serial-port.c | 47 | ||||
-rw-r--r-- | src/mm-serial-port.h | 2 |
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 */ |