serial: add support to optionally send line-feed at the end of AT commands.
This commit is contained in:

committed by
Aleksander Morgado

parent
98772f2ec9
commit
633708b364
40
src/mm-at-serial-port.c
Normal file → Executable file
40
src/mm-at-serial-port.c
Normal file → Executable file
@@ -33,6 +33,7 @@ enum {
|
|||||||
PROP_REMOVE_ECHO,
|
PROP_REMOVE_ECHO,
|
||||||
PROP_INIT_SEQUENCE_ENABLED,
|
PROP_INIT_SEQUENCE_ENABLED,
|
||||||
PROP_INIT_SEQUENCE,
|
PROP_INIT_SEQUENCE,
|
||||||
|
PROP_SEND_LF,
|
||||||
LAST_PROP
|
LAST_PROP
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ typedef struct {
|
|||||||
gboolean remove_echo;
|
gboolean remove_echo;
|
||||||
guint init_sequence_enabled;
|
guint init_sequence_enabled;
|
||||||
gchar **init_sequence;
|
gchar **init_sequence;
|
||||||
|
gboolean send_lf;
|
||||||
} MMAtSerialPortPrivate;
|
} MMAtSerialPortPrivate;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -286,7 +288,7 @@ parse_unsolicited (MMSerialPort *port, GByteArray *response)
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static GByteArray *
|
static GByteArray *
|
||||||
at_command_to_byte_array (const char *command, gboolean is_raw)
|
at_command_to_byte_array (const char *command, gboolean is_raw, gboolean send_lf)
|
||||||
{
|
{
|
||||||
GByteArray *buf;
|
GByteArray *buf;
|
||||||
int cmdlen;
|
int cmdlen;
|
||||||
@@ -294,7 +296,7 @@ at_command_to_byte_array (const char *command, gboolean is_raw)
|
|||||||
g_return_val_if_fail (command != NULL, NULL);
|
g_return_val_if_fail (command != NULL, NULL);
|
||||||
|
|
||||||
cmdlen = strlen (command);
|
cmdlen = strlen (command);
|
||||||
buf = g_byte_array_sized_new (cmdlen + 3);
|
buf = g_byte_array_sized_new (cmdlen + 4);
|
||||||
|
|
||||||
if (!is_raw) {
|
if (!is_raw) {
|
||||||
/* Make sure there's an AT in the front */
|
/* Make sure there's an AT in the front */
|
||||||
@@ -306,8 +308,15 @@ at_command_to_byte_array (const char *command, gboolean is_raw)
|
|||||||
|
|
||||||
if (!is_raw) {
|
if (!is_raw) {
|
||||||
/* Make sure there's a trailing carriage return */
|
/* Make sure there's a trailing carriage return */
|
||||||
if (command[cmdlen - 1] != '\r')
|
if ((cmdlen == 0) ||
|
||||||
g_byte_array_append (buf, (const guint8 *) "\r", 1);
|
(command[cmdlen - 1] != '\r' && (cmdlen == 1 || command[cmdlen - 2] != '\r')))
|
||||||
|
g_byte_array_append (buf, (const guint8 *) "\r", 1);
|
||||||
|
if (send_lf) {
|
||||||
|
/* Make sure there's a trailing line-feed */
|
||||||
|
if ((cmdlen == 0) ||
|
||||||
|
(command[cmdlen - 1] != '\n' && (cmdlen == 1 || command[cmdlen - 2] != '\n')))
|
||||||
|
g_byte_array_append (buf, (const guint8 *) "\n", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
@@ -323,12 +332,13 @@ mm_at_serial_port_queue_command (MMAtSerialPort *self,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GByteArray *buf;
|
GByteArray *buf;
|
||||||
|
MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
|
||||||
|
|
||||||
g_return_if_fail (self != NULL);
|
g_return_if_fail (self != NULL);
|
||||||
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
|
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
|
||||||
g_return_if_fail (command != NULL);
|
g_return_if_fail (command != NULL);
|
||||||
|
|
||||||
buf = at_command_to_byte_array (command, is_raw);
|
buf = at_command_to_byte_array (command, is_raw, priv->send_lf);
|
||||||
g_return_if_fail (buf != NULL);
|
g_return_if_fail (buf != NULL);
|
||||||
|
|
||||||
mm_serial_port_queue_command (MM_SERIAL_PORT (self),
|
mm_serial_port_queue_command (MM_SERIAL_PORT (self),
|
||||||
@@ -350,12 +360,13 @@ mm_at_serial_port_queue_command_cached (MMAtSerialPort *self,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GByteArray *buf;
|
GByteArray *buf;
|
||||||
|
MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
|
||||||
|
|
||||||
g_return_if_fail (self != NULL);
|
g_return_if_fail (self != NULL);
|
||||||
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
|
g_return_if_fail (MM_IS_AT_SERIAL_PORT (self));
|
||||||
g_return_if_fail (command != NULL);
|
g_return_if_fail (command != NULL);
|
||||||
|
|
||||||
buf = at_command_to_byte_array (command, is_raw);
|
buf = at_command_to_byte_array (command, is_raw, priv->send_lf);
|
||||||
g_return_if_fail (buf != NULL);
|
g_return_if_fail (buf != NULL);
|
||||||
|
|
||||||
mm_serial_port_queue_command_cached (MM_SERIAL_PORT (self),
|
mm_serial_port_queue_command_cached (MM_SERIAL_PORT (self),
|
||||||
@@ -475,6 +486,9 @@ mm_at_serial_port_init (MMAtSerialPort *self)
|
|||||||
priv->remove_echo = TRUE;
|
priv->remove_echo = TRUE;
|
||||||
/* By default, run init sequence during first port opening */
|
/* By default, run init sequence during first port opening */
|
||||||
priv->init_sequence_enabled = TRUE;
|
priv->init_sequence_enabled = TRUE;
|
||||||
|
|
||||||
|
/* By default, don't send line feed */
|
||||||
|
priv->send_lf = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -494,6 +508,9 @@ set_property (GObject *object, guint prop_id,
|
|||||||
g_strfreev (priv->init_sequence);
|
g_strfreev (priv->init_sequence);
|
||||||
priv->init_sequence = g_value_dup_boxed (value);
|
priv->init_sequence = g_value_dup_boxed (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SEND_LF:
|
||||||
|
priv->send_lf = 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;
|
||||||
@@ -516,6 +533,9 @@ get_property (GObject *object, guint prop_id,
|
|||||||
case PROP_INIT_SEQUENCE:
|
case PROP_INIT_SEQUENCE:
|
||||||
g_value_set_boxed (value, priv->init_sequence);
|
g_value_set_boxed (value, priv->init_sequence);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SEND_LF:
|
||||||
|
g_value_set_boolean (value, priv->send_lf);
|
||||||
|
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;
|
||||||
@@ -590,4 +610,12 @@ mm_at_serial_port_class_init (MMAtSerialPortClass *klass)
|
|||||||
"Initialization sequence",
|
"Initialization sequence",
|
||||||
G_TYPE_STRV,
|
G_TYPE_STRV,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class, PROP_SEND_LF,
|
||||||
|
g_param_spec_boolean (MM_AT_SERIAL_PORT_SEND_LF,
|
||||||
|
"Send LF",
|
||||||
|
"Send line-feed at the end of each AT command sent",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
}
|
}
|
||||||
|
@@ -69,6 +69,8 @@ typedef void (*MMAtSerialResponseFn) (MMAtSerialPort *port,
|
|||||||
#define MM_AT_SERIAL_PORT_INIT_SEQUENCE_ENABLED "init-sequence-enabled"
|
#define MM_AT_SERIAL_PORT_INIT_SEQUENCE_ENABLED "init-sequence-enabled"
|
||||||
#define MM_AT_SERIAL_PORT_INIT_SEQUENCE "init-sequence"
|
#define MM_AT_SERIAL_PORT_INIT_SEQUENCE "init-sequence"
|
||||||
|
|
||||||
|
#define MM_AT_SERIAL_PORT_SEND_LF "send-lf"
|
||||||
|
|
||||||
struct _MMAtSerialPort {
|
struct _MMAtSerialPort {
|
||||||
MMSerialPort parent;
|
MMSerialPort parent;
|
||||||
};
|
};
|
||||||
|
@@ -81,6 +81,7 @@ struct _MMPluginPrivate {
|
|||||||
MMPortProbeAtCommand *custom_at_probe;
|
MMPortProbeAtCommand *custom_at_probe;
|
||||||
guint64 send_delay;
|
guint64 send_delay;
|
||||||
gboolean remove_echo;
|
gboolean remove_echo;
|
||||||
|
gboolean send_lf;
|
||||||
|
|
||||||
/* Probing setup and/or post-probing filter.
|
/* Probing setup and/or post-probing filter.
|
||||||
* Plugins may use this method to decide whether they support a given
|
* Plugins may use this method to decide whether they support a given
|
||||||
@@ -112,6 +113,7 @@ enum {
|
|||||||
PROP_CUSTOM_INIT,
|
PROP_CUSTOM_INIT,
|
||||||
PROP_SEND_DELAY,
|
PROP_SEND_DELAY,
|
||||||
PROP_REMOVE_ECHO,
|
PROP_REMOVE_ECHO,
|
||||||
|
PROP_SEND_LF,
|
||||||
LAST_PROP
|
LAST_PROP
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -753,6 +755,7 @@ mm_plugin_supports_port (MMPlugin *self,
|
|||||||
ctx->flags,
|
ctx->flags,
|
||||||
self->priv->send_delay,
|
self->priv->send_delay,
|
||||||
self->priv->remove_echo,
|
self->priv->remove_echo,
|
||||||
|
self->priv->send_lf,
|
||||||
self->priv->custom_at_probe,
|
self->priv->custom_at_probe,
|
||||||
self->priv->custom_init,
|
self->priv->custom_init,
|
||||||
(GAsyncReadyCallback)port_probe_run_ready,
|
(GAsyncReadyCallback)port_probe_run_ready,
|
||||||
@@ -888,6 +891,7 @@ mm_plugin_init (MMPlugin *self)
|
|||||||
/* Defaults */
|
/* Defaults */
|
||||||
self->priv->send_delay = 100000;
|
self->priv->send_delay = 100000;
|
||||||
self->priv->remove_echo = TRUE;
|
self->priv->remove_echo = TRUE;
|
||||||
|
self->priv->send_lf = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -987,6 +991,10 @@ set_property (GObject *object,
|
|||||||
/* Construct only */
|
/* Construct only */
|
||||||
self->priv->remove_echo = g_value_get_boolean (value);
|
self->priv->remove_echo = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SEND_LF:
|
||||||
|
/* Construct only */
|
||||||
|
self->priv->send_lf = 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;
|
||||||
@@ -1068,6 +1076,9 @@ get_property (GObject *object,
|
|||||||
case PROP_REMOVE_ECHO:
|
case PROP_REMOVE_ECHO:
|
||||||
g_value_set_boolean (value, self->priv->remove_echo);
|
g_value_set_boolean (value, self->priv->remove_echo);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SEND_LF:
|
||||||
|
g_value_set_boolean (value, self->priv->send_lf);
|
||||||
|
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;
|
||||||
@@ -1302,4 +1313,12 @@ mm_plugin_class_init (MMPluginClass *klass)
|
|||||||
"Remove echo out of the AT responses",
|
"Remove echo out of the AT responses",
|
||||||
TRUE,
|
TRUE,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||||
|
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class, PROP_SEND_LF,
|
||||||
|
g_param_spec_boolean (MM_PLUGIN_SEND_LF,
|
||||||
|
"Send LF",
|
||||||
|
"Send line-feed at the end of each AT command sent",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||||
}
|
}
|
||||||
|
@@ -60,6 +60,7 @@
|
|||||||
#define MM_PLUGIN_CUSTOM_AT_PROBE "custom-at-probe"
|
#define MM_PLUGIN_CUSTOM_AT_PROBE "custom-at-probe"
|
||||||
#define MM_PLUGIN_SEND_DELAY "send-delay"
|
#define MM_PLUGIN_SEND_DELAY "send-delay"
|
||||||
#define MM_PLUGIN_REMOVE_ECHO "remove-echo"
|
#define MM_PLUGIN_REMOVE_ECHO "remove-echo"
|
||||||
|
#define MM_PLUGIN_SEND_LF "send-lf"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED = 0x0,
|
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED = 0x0,
|
||||||
|
@@ -85,6 +85,8 @@ typedef struct {
|
|||||||
guint64 at_send_delay;
|
guint64 at_send_delay;
|
||||||
/* Flag to leave/remove echo in AT responses */
|
/* Flag to leave/remove echo in AT responses */
|
||||||
gboolean at_remove_echo;
|
gboolean at_remove_echo;
|
||||||
|
/* Flag to send line-feed at the end of AT commands */
|
||||||
|
gboolean at_send_lf;
|
||||||
/* Number of times we tried to open the AT port */
|
/* Number of times we tried to open the AT port */
|
||||||
guint at_open_tries;
|
guint at_open_tries;
|
||||||
/* Custom initialization setup */
|
/* Custom initialization setup */
|
||||||
@@ -975,6 +977,7 @@ serial_open_at (MMPortProbe *self)
|
|||||||
g_object_set (task->serial,
|
g_object_set (task->serial,
|
||||||
MM_SERIAL_PORT_SEND_DELAY, task->at_send_delay,
|
MM_SERIAL_PORT_SEND_DELAY, task->at_send_delay,
|
||||||
MM_AT_SERIAL_PORT_REMOVE_ECHO, task->at_remove_echo,
|
MM_AT_SERIAL_PORT_REMOVE_ECHO, task->at_remove_echo,
|
||||||
|
MM_AT_SERIAL_PORT_SEND_LF, task->at_send_lf,
|
||||||
MM_PORT_CARRIER_DETECT, FALSE,
|
MM_PORT_CARRIER_DETECT, FALSE,
|
||||||
MM_SERIAL_PORT_SPEW_CONTROL, TRUE,
|
MM_SERIAL_PORT_SPEW_CONTROL, TRUE,
|
||||||
NULL);
|
NULL);
|
||||||
@@ -1096,6 +1099,7 @@ mm_port_probe_run (MMPortProbe *self,
|
|||||||
MMPortProbeFlag flags,
|
MMPortProbeFlag flags,
|
||||||
guint64 at_send_delay,
|
guint64 at_send_delay,
|
||||||
gboolean at_remove_echo,
|
gboolean at_remove_echo,
|
||||||
|
gboolean at_send_lf,
|
||||||
const MMPortProbeAtCommand *at_custom_probe,
|
const MMPortProbeAtCommand *at_custom_probe,
|
||||||
const MMAsyncMethod *at_custom_init,
|
const MMAsyncMethod *at_custom_init,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
@@ -1115,6 +1119,7 @@ mm_port_probe_run (MMPortProbe *self,
|
|||||||
task = g_new0 (PortProbeRunTask, 1);
|
task = g_new0 (PortProbeRunTask, 1);
|
||||||
task->at_send_delay = at_send_delay;
|
task->at_send_delay = at_send_delay;
|
||||||
task->at_remove_echo = at_remove_echo;
|
task->at_remove_echo = at_remove_echo;
|
||||||
|
task->at_send_lf = at_send_lf;
|
||||||
task->flags = MM_PORT_PROBE_NONE;
|
task->flags = MM_PORT_PROBE_NONE;
|
||||||
task->at_custom_probe = at_custom_probe;
|
task->at_custom_probe = at_custom_probe;
|
||||||
task->at_custom_init = at_custom_init ? (MMPortProbeAtCustomInit)at_custom_init->async : NULL;
|
task->at_custom_init = at_custom_init ? (MMPortProbeAtCustomInit)at_custom_init->async : NULL;
|
||||||
|
@@ -106,6 +106,7 @@ void mm_port_probe_run (MMPortProbe *self,
|
|||||||
MMPortProbeFlag flags,
|
MMPortProbeFlag flags,
|
||||||
guint64 at_send_delay,
|
guint64 at_send_delay,
|
||||||
gboolean at_remove_echo,
|
gboolean at_remove_echo,
|
||||||
|
gboolean at_send_lf,
|
||||||
const MMPortProbeAtCommand *at_custom_probe,
|
const MMPortProbeAtCommand *at_custom_probe,
|
||||||
const MMAsyncMethod *at_custom_init,
|
const MMAsyncMethod *at_custom_init,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
|
Reference in New Issue
Block a user