aboutsummaryrefslogtreecommitdiff
path: root/src/mm-serial-port.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-serial-port.c')
-rw-r--r--src/mm-serial-port.c120
1 files changed, 80 insertions, 40 deletions
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index 18a616d..46050cf 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -45,6 +45,7 @@ enum {
PROP_SEND_DELAY,
PROP_FD,
PROP_SPEW_CONTROL,
+ PROP_FLASH_OK,
LAST_PROP
};
@@ -69,6 +70,7 @@ typedef struct {
guint stopbits;
guint64 send_delay;
gboolean spew_control;
+ gboolean flash_ok;
guint queue_id;
guint watch_id;
@@ -627,8 +629,12 @@ data_available (GIOChannel *source,
gsize bytes_read;
GIOStatus status;
MMQueueData *info;
+ const char *device;
if (condition & G_IO_HUP) {
+ device = mm_port_get_device (MM_PORT (self));
+ mm_dbg ("(%s) unexpected port hangup!", device);
+
if (priv->response->len)
g_byte_array_remove_range (priv->response, 0, priv->response->len);
mm_serial_port_close_force (self);
@@ -719,6 +725,7 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
char *devfile;
const char *device;
struct serial_struct sinfo;
+ GTimeVal tv_start, tv_end;
g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
@@ -733,6 +740,8 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
mm_info ("(%s) opening serial port...", device);
+ g_get_current_time (&tv_start);
+
/* Only open a new file descriptor if we weren't given one already */
if (priv->fd < 0) {
devfile = g_strdup_printf ("/dev/%s", device);
@@ -781,6 +790,11 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
ioctl (priv->fd, TIOCSSERIAL, &sinfo);
}
+ g_get_current_time (&tv_end);
+
+ if (tv_end.tv_sec - tv_start.tv_sec > 7)
+ mm_warn ("(%s): open blocked by driver for more than 7 seconds!", device);
+
priv->channel = g_io_channel_unix_new (priv->fd);
g_io_channel_set_encoding (priv->channel, NULL, NULL);
priv->watch_id = g_io_add_watch (priv->channel,
@@ -870,8 +884,8 @@ mm_serial_port_close (MMSerialPort *self)
* that data to send before giving up and returning from close().
* Log that. See GNOME bug #630670 for more details.
*/
- if (tv_end.tv_sec - tv_start.tv_sec > 20)
- mm_warn ("(%s): close blocked by driver for more than 20 seconds!", device);
+ if (tv_end.tv_sec - tv_start.tv_sec > 7)
+ mm_warn ("(%s): close blocked by driver for more than 7 seconds!", device);
}
/* Clear the command queue */
@@ -995,13 +1009,6 @@ mm_serial_port_queue_command_cached (MMSerialPort *self,
internal_queue_command (self, command, take_command, TRUE, timeout_seconds, callback, user_data);
}
-typedef struct {
- MMSerialPort *port;
- speed_t current_speed;
- MMSerialFlashFn callback;
- gpointer user_data;
-} FlashInfo;
-
static gboolean
get_speed (MMSerialPort *self, speed_t *speed, GError **error)
{
@@ -1076,6 +1083,13 @@ set_speed (MMSerialPort *self, speed_t speed, GError **error)
return TRUE;
}
+typedef struct {
+ MMSerialPort *port;
+ speed_t current_speed;
+ MMSerialFlashFn callback;
+ gpointer user_data;
+} FlashInfo;
+
static gboolean
flash_do (gpointer data)
{
@@ -1085,13 +1099,15 @@ flash_do (gpointer data)
priv->flash_id = 0;
- if (info->current_speed) {
- if (!set_speed (info->port, info->current_speed, &error))
- g_assert (error);
- } else {
- error = g_error_new_literal (MM_SERIAL_ERROR,
- MM_SERIAL_ERROR_FLASH_FAILED,
- "Failed to retrieve current speed");
+ if (priv->flash_ok) {
+ if (info->current_speed) {
+ if (!set_speed (info->port, info->current_speed, &error))
+ g_assert (error);
+ } else {
+ error = g_error_new_literal (MM_SERIAL_ERROR,
+ MM_SERIAL_ERROR_FLASH_FAILED,
+ "Failed to retrieve current speed");
+ }
}
info->callback (info->port, error, info->user_data);
@@ -1107,9 +1123,8 @@ mm_serial_port_flash (MMSerialPort *self,
MMSerialFlashFn callback,
gpointer user_data)
{
- FlashInfo *info;
+ FlashInfo *info = NULL;
MMSerialPortPrivate *priv;
- speed_t cur_speed = 0;
GError *error = NULL;
gboolean success;
@@ -1122,43 +1137,45 @@ mm_serial_port_flash (MMSerialPort *self,
error = g_error_new_literal (MM_SERIAL_ERROR,
MM_SERIAL_ERROR_NOT_OPEN,
"The serial port is not open.");
- callback (self, error, user_data);
- g_error_free (error);
- return FALSE;
+ goto error;
}
if (priv->flash_id > 0) {
error = g_error_new_literal (MM_MODEM_ERROR,
MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
"Modem is already being flashed.");
- callback (self, error, user_data);
- g_error_free (error);
- return FALSE;
- }
-
- success = get_speed (self, &cur_speed, &error);
- if (!success && !ignore_errors) {
- callback (self, error, user_data);
- g_error_free (error);
- return FALSE;
+ goto error;
}
- g_clear_error (&error);
info = g_slice_new0 (FlashInfo);
info->port = self;
- info->current_speed = cur_speed;
info->callback = callback;
info->user_data = user_data;
- success = set_speed (self, B0, &error);
- if (!success && !ignore_errors) {
- callback (self, error, user_data);
- g_error_free (error);
- return FALSE;
- }
+ if (priv->flash_ok) {
+ /* Grab current speed so we can reset it after flashing */
+ success = get_speed (self, &info->current_speed, &error);
+ if (!success && !ignore_errors)
+ goto error;
+ g_clear_error (&error);
+
+ success = set_speed (self, B0, &error);
+ if (!success && !ignore_errors)
+ goto error;
+ g_clear_error (&error);
+
+ priv->flash_id = g_timeout_add (flash_time, flash_do, info);
+ } else
+ priv->flash_id = g_idle_add (flash_do, info);
- priv->flash_id = g_timeout_add (flash_time, flash_do, info);
return TRUE;
+
+error:
+ callback (self, error, user_data);
+ g_clear_error (&error);
+ if (info)
+ g_slice_free (FlashInfo, info);
+ return FALSE;
}
void
@@ -1176,6 +1193,14 @@ mm_serial_port_flash_cancel (MMSerialPort *self)
}
}
+gboolean
+mm_serial_port_get_flash_ok (MMSerialPort *self)
+{
+ g_return_val_if_fail (MM_IS_SERIAL_PORT (self), TRUE);
+
+ return MM_SERIAL_PORT_GET_PRIVATE (self)->flash_ok;
+}
+
/*****************************************************************************/
MMSerialPort *
@@ -1276,6 +1301,9 @@ set_property (GObject *object, guint prop_id,
case PROP_SPEW_CONTROL:
priv->spew_control = g_value_get_boolean (value);
break;
+ case PROP_FLASH_OK:
+ priv->flash_ok = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1310,6 +1338,9 @@ get_property (GObject *object, guint prop_id,
case PROP_SPEW_CONTROL:
g_value_set_boolean (value, priv->spew_control);
break;
+ case PROP_FLASH_OK:
+ g_value_set_boolean (value, priv->flash_ok);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1420,6 +1451,15 @@ mm_serial_port_class_init (MMSerialPortClass *klass)
FALSE,
G_PARAM_READWRITE));
+ g_object_class_install_property
+ (object_class, PROP_FLASH_OK,
+ g_param_spec_boolean (MM_SERIAL_PORT_FLASH_OK,
+ "FlaskOk",
+ "Flashing the port (0 baud for a short period) "
+ "is allowed.",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
/* Signals */
g_signal_new ("buffer-full",
G_OBJECT_CLASS_TYPE (object_class),