From a09050a7f63a262bf90dcb1c7a41f9cfd205db43 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Wed, 5 Feb 2014 08:38:26 +0100 Subject: Imported Upstream version 0.5 --- src/mm-serial-port.c | 120 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 40 deletions(-) (limited to 'src/mm-serial-port.c') 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), -- cgit v1.2.3