core: allow ports to skip flash behavior (bgo #650740)
Flashing is a technique to break out of the data/PPP stream and re-enter command stream (like +++) and MM uses it in the generic paths in various cases. But devices that don't need it (ie, ones with at least one AT capable port that won't be used for data) now sometimes appear to have side-effects. The Ericsson F5521gw firmware R2A07 resets port attributes like echo and &C and such when the port is flashed, leading to confusion on the part of MM. Since the Ericsson devices will always have at least one free AT port they don't need flashing anyway.
This commit is contained in:
@@ -46,6 +46,7 @@ enum {
|
|||||||
PROP_FD,
|
PROP_FD,
|
||||||
PROP_SPEW_CONTROL,
|
PROP_SPEW_CONTROL,
|
||||||
PROP_RTS_CTS,
|
PROP_RTS_CTS,
|
||||||
|
PROP_FLASH_OK,
|
||||||
|
|
||||||
LAST_PROP
|
LAST_PROP
|
||||||
};
|
};
|
||||||
@@ -80,6 +81,7 @@ typedef struct {
|
|||||||
guint64 send_delay;
|
guint64 send_delay;
|
||||||
gboolean spew_control;
|
gboolean spew_control;
|
||||||
gboolean rts_cts;
|
gboolean rts_cts;
|
||||||
|
gboolean flash_ok;
|
||||||
|
|
||||||
guint queue_id;
|
guint queue_id;
|
||||||
guint watch_id;
|
guint watch_id;
|
||||||
@@ -1068,13 +1070,6 @@ mm_serial_port_queue_command_cached (MMSerialPort *self,
|
|||||||
internal_queue_command (self, command, take_command, TRUE, timeout_seconds, callback, user_data);
|
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
|
static gboolean
|
||||||
get_speed (MMSerialPort *self, speed_t *speed, GError **error)
|
get_speed (MMSerialPort *self, speed_t *speed, GError **error)
|
||||||
{
|
{
|
||||||
@@ -1154,6 +1149,13 @@ set_speed (MMSerialPort *self, speed_t speed, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MMSerialPort *port;
|
||||||
|
speed_t current_speed;
|
||||||
|
MMSerialFlashFn callback;
|
||||||
|
gpointer user_data;
|
||||||
|
} FlashInfo;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
flash_do (gpointer data)
|
flash_do (gpointer data)
|
||||||
{
|
{
|
||||||
@@ -1163,13 +1165,15 @@ flash_do (gpointer data)
|
|||||||
|
|
||||||
priv->flash_id = 0;
|
priv->flash_id = 0;
|
||||||
|
|
||||||
if (info->current_speed) {
|
if (priv->flash_ok) {
|
||||||
if (!set_speed (info->port, info->current_speed, &error))
|
if (info->current_speed) {
|
||||||
g_assert (error);
|
if (!set_speed (info->port, info->current_speed, &error))
|
||||||
} else {
|
g_assert (error);
|
||||||
error = g_error_new_literal (MM_SERIAL_ERROR,
|
} else {
|
||||||
MM_SERIAL_ERROR_FLASH_FAILED,
|
error = g_error_new_literal (MM_SERIAL_ERROR,
|
||||||
"Failed to retrieve current speed");
|
MM_SERIAL_ERROR_FLASH_FAILED,
|
||||||
|
"Failed to retrieve current speed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info->callback (info->port, error, info->user_data);
|
info->callback (info->port, error, info->user_data);
|
||||||
@@ -1185,9 +1189,8 @@ mm_serial_port_flash (MMSerialPort *self,
|
|||||||
MMSerialFlashFn callback,
|
MMSerialFlashFn callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
FlashInfo *info;
|
FlashInfo *info = NULL;
|
||||||
MMSerialPortPrivate *priv;
|
MMSerialPortPrivate *priv;
|
||||||
speed_t cur_speed = 0;
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
|
||||||
@@ -1200,43 +1203,43 @@ mm_serial_port_flash (MMSerialPort *self,
|
|||||||
error = g_error_new_literal (MM_SERIAL_ERROR,
|
error = g_error_new_literal (MM_SERIAL_ERROR,
|
||||||
MM_SERIAL_ERROR_NOT_OPEN,
|
MM_SERIAL_ERROR_NOT_OPEN,
|
||||||
"The serial port is not open.");
|
"The serial port is not open.");
|
||||||
callback (self, error, user_data);
|
goto error;
|
||||||
g_error_free (error);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->flash_id > 0) {
|
if (priv->flash_id > 0) {
|
||||||
error = g_error_new_literal (MM_MODEM_ERROR,
|
error = g_error_new_literal (MM_MODEM_ERROR,
|
||||||
MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
|
MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
|
||||||
"Modem is already being flashed.");
|
"Modem is already being flashed.");
|
||||||
callback (self, error, user_data);
|
goto error;
|
||||||
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;
|
|
||||||
}
|
|
||||||
g_clear_error (&error);
|
|
||||||
|
|
||||||
info = g_slice_new0 (FlashInfo);
|
info = g_slice_new0 (FlashInfo);
|
||||||
info->port = self;
|
info->port = self;
|
||||||
info->current_speed = cur_speed;
|
|
||||||
info->callback = callback;
|
info->callback = callback;
|
||||||
info->user_data = user_data;
|
info->user_data = user_data;
|
||||||
|
|
||||||
success = set_speed (self, B0, &error);
|
if (priv->flash_ok) {
|
||||||
if (!success && !ignore_errors) {
|
/* Grab current speed so we can reset it after flashing */
|
||||||
callback (self, error, user_data);
|
success = get_speed (self, &info->current_speed, &error);
|
||||||
g_error_free (error);
|
if (!success && !ignore_errors)
|
||||||
return FALSE;
|
goto error;
|
||||||
}
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
success = set_speed (self, B0, &error);
|
||||||
|
if (!success && !ignore_errors)
|
||||||
|
goto 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;
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
callback (self, error, user_data);
|
||||||
|
g_clear_error (&error);
|
||||||
|
if (info)
|
||||||
|
g_slice_free (FlashInfo, info);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1254,6 +1257,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 *
|
MMSerialPort *
|
||||||
@@ -1357,6 +1368,9 @@ set_property (GObject *object, guint prop_id,
|
|||||||
case PROP_RTS_CTS:
|
case PROP_RTS_CTS:
|
||||||
priv->rts_cts = g_value_get_boolean (value);
|
priv->rts_cts = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_FLASH_OK:
|
||||||
|
priv->flash_ok = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -1394,6 +1408,9 @@ get_property (GObject *object, guint prop_id,
|
|||||||
case PROP_RTS_CTS:
|
case PROP_RTS_CTS:
|
||||||
g_value_set_boolean (value, priv->rts_cts);
|
g_value_set_boolean (value, priv->rts_cts);
|
||||||
break;
|
break;
|
||||||
|
case PROP_FLASH_OK:
|
||||||
|
g_value_set_boolean (value, priv->flash_ok);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -1512,6 +1529,15 @@ mm_serial_port_class_init (MMSerialPortClass *klass)
|
|||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_READWRITE));
|
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));
|
||||||
|
|
||||||
/* Signals */
|
/* Signals */
|
||||||
signals[BUFFER_FULL] =
|
signals[BUFFER_FULL] =
|
||||||
g_signal_new ("buffer-full",
|
g_signal_new ("buffer-full",
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#define MM_SERIAL_PORT_RTS_CTS "rts-cts"
|
#define MM_SERIAL_PORT_RTS_CTS "rts-cts"
|
||||||
#define MM_SERIAL_PORT_FD "fd" /* Construct-only */
|
#define MM_SERIAL_PORT_FD "fd" /* Construct-only */
|
||||||
#define MM_SERIAL_PORT_SPEW_CONTROL "spew-control" /* Construct-only */
|
#define MM_SERIAL_PORT_SPEW_CONTROL "spew-control" /* Construct-only */
|
||||||
|
#define MM_SERIAL_PORT_FLASH_OK "flash-ok" /* Construct-only */
|
||||||
|
|
||||||
typedef struct _MMSerialPort MMSerialPort;
|
typedef struct _MMSerialPort MMSerialPort;
|
||||||
typedef struct _MMSerialPortClass MMSerialPortClass;
|
typedef struct _MMSerialPortClass MMSerialPortClass;
|
||||||
@@ -123,8 +124,11 @@ gboolean mm_serial_port_flash (MMSerialPort *self,
|
|||||||
gboolean ignore_errors,
|
gboolean ignore_errors,
|
||||||
MMSerialFlashFn callback,
|
MMSerialFlashFn callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
void mm_serial_port_flash_cancel (MMSerialPort *self);
|
void mm_serial_port_flash_cancel (MMSerialPort *self);
|
||||||
|
|
||||||
|
gboolean mm_serial_port_get_flash_ok (MMSerialPort *self);
|
||||||
|
|
||||||
void mm_serial_port_queue_command (MMSerialPort *self,
|
void mm_serial_port_queue_command (MMSerialPort *self,
|
||||||
GByteArray *command,
|
GByteArray *command,
|
||||||
gboolean take_command,
|
gboolean take_command,
|
||||||
|
Reference in New Issue
Block a user