port-serial: add flow control property
Add flow control property to the MMPortSerial class, and use it when setting the port flow control.
This commit is contained in:
committed by
Dan Williams
parent
a1c27bf89d
commit
4e69c10c2d
+75
-29
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "mm-port-serial.h"
|
||||
#include "mm-log.h"
|
||||
#include "mm-helper-enums-types.h"
|
||||
|
||||
static gboolean port_serial_queue_process (gpointer data);
|
||||
static void port_serial_schedule_queue_process (MMPortSerial *self,
|
||||
@@ -53,6 +54,7 @@ enum {
|
||||
PROP_BITS,
|
||||
PROP_PARITY,
|
||||
PROP_STOPBITS,
|
||||
PROP_FLOW_CONTROL,
|
||||
PROP_SEND_DELAY,
|
||||
PROP_FD,
|
||||
PROP_SPEW_CONTROL,
|
||||
@@ -94,6 +96,7 @@ struct _MMPortSerialPrivate {
|
||||
guint bits;
|
||||
char parity;
|
||||
guint stopbits;
|
||||
MMFlowControl flow_control;
|
||||
guint64 send_delay;
|
||||
gboolean spew_control;
|
||||
gboolean flash_ok;
|
||||
@@ -403,6 +406,48 @@ internal_tcsetattr (MMPortSerial *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_flow_control_termios (MMPortSerial *self,
|
||||
MMFlowControl flow_control,
|
||||
struct termios *options)
|
||||
{
|
||||
gboolean had_xon_xoff;
|
||||
gboolean had_rts_cts;
|
||||
tcflag_t iflag_orig, cflag_orig;
|
||||
|
||||
iflag_orig = options->c_iflag;
|
||||
cflag_orig = options->c_cflag;
|
||||
|
||||
had_xon_xoff = !!(options->c_iflag & (IXON | IXOFF));
|
||||
options->c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
|
||||
had_rts_cts = !!(options->c_cflag & (CRTSCTS));
|
||||
options->c_cflag &= ~(CRTSCTS);
|
||||
|
||||
/* setup the requested flags */
|
||||
switch (flow_control) {
|
||||
case MM_FLOW_CONTROL_XON_XOFF:
|
||||
mm_dbg ("(%s): enabling XON/XOFF flow control", mm_port_get_device (MM_PORT (self)));
|
||||
options->c_iflag |= (IXON | IXOFF | IXANY);
|
||||
break;
|
||||
case MM_FLOW_CONTROL_RTS_CTS:
|
||||
mm_dbg ("(%s): enabling RTS/CTS flow control", mm_port_get_device (MM_PORT (self)));
|
||||
options->c_cflag |= (CRTSCTS);
|
||||
break;
|
||||
case MM_FLOW_CONTROL_NONE:
|
||||
case MM_FLOW_CONTROL_UNKNOWN:
|
||||
if (had_xon_xoff)
|
||||
mm_dbg ("(%s): disabling XON/XOFF flow control", mm_port_get_device (MM_PORT (self)));
|
||||
if (had_rts_cts)
|
||||
mm_dbg ("(%s): disabling RTS/CTS flow control", mm_port_get_device (MM_PORT (self)));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return iflag_orig != options->c_iflag || cflag_orig != options->c_cflag;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
real_config_fd (MMPortSerial *self, int fd, GError **error)
|
||||
{
|
||||
@@ -471,6 +516,12 @@ real_config_fd (MMPortSerial *self, int fd, GError **error)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mm_dbg ("(%s): flow control is: %d",
|
||||
mm_port_get_device (MM_PORT (self)),
|
||||
self->priv->flow_control);
|
||||
|
||||
set_flow_control_termios (self, self->priv->flow_control, &stbuf);
|
||||
|
||||
return internal_tcsetattr (self, fd, &stbuf, error);
|
||||
}
|
||||
|
||||
@@ -1787,8 +1838,6 @@ mm_port_serial_set_flow_control (MMPortSerial *self,
|
||||
GError **error)
|
||||
{
|
||||
struct termios options;
|
||||
gboolean had_xon_xoff;
|
||||
gboolean had_rts_cts;
|
||||
|
||||
/* retrieve current settings */
|
||||
memset (&options, 0, sizeof (struct termios));
|
||||
@@ -1798,37 +1847,18 @@ mm_port_serial_set_flow_control (MMPortSerial *self,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* clear all flow control flags */
|
||||
|
||||
had_xon_xoff = !!(options.c_iflag & (IXON | IXOFF));
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
|
||||
had_rts_cts = !!(options.c_cflag & (CRTSCTS));
|
||||
options.c_cflag &= ~(CRTSCTS);
|
||||
|
||||
/* setup the requested flags */
|
||||
switch (flow_control) {
|
||||
case MM_FLOW_CONTROL_XON_XOFF:
|
||||
mm_dbg ("(%s): enabling XON/XOFF flow control", mm_port_get_device (MM_PORT (self)));
|
||||
options.c_iflag |= (IXON | IXOFF | IXANY);
|
||||
break;
|
||||
case MM_FLOW_CONTROL_RTS_CTS:
|
||||
mm_dbg ("(%s): enabling RTS/CTS flow control", mm_port_get_device (MM_PORT (self)));
|
||||
options.c_cflag |= (CRTSCTS);
|
||||
break;
|
||||
case MM_FLOW_CONTROL_NONE:
|
||||
if (had_xon_xoff)
|
||||
mm_dbg ("(%s): disabling XON/XOFF flow control", mm_port_get_device (MM_PORT (self)));
|
||||
if (had_rts_cts)
|
||||
mm_dbg ("(%s): disabling RTS/CTS flow control", mm_port_get_device (MM_PORT (self)));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
/* Return if current settings are already what we want */
|
||||
if (!set_flow_control_termios (self, flow_control, &options))
|
||||
return TRUE;
|
||||
|
||||
return internal_tcsetattr (self, self->priv->fd, &options, error);
|
||||
}
|
||||
|
||||
MMFlowControl mm_port_serial_get_flow_control (MMPortSerial *self)
|
||||
{
|
||||
return self->priv->flow_control;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
MMPortSerial *
|
||||
@@ -1895,6 +1925,7 @@ mm_port_serial_init (MMPortSerial *self)
|
||||
self->priv->bits = 8;
|
||||
self->priv->parity = 'n';
|
||||
self->priv->stopbits = 1;
|
||||
self->priv->flow_control = MM_FLOW_CONTROL_UNKNOWN;
|
||||
self->priv->send_delay = 1000;
|
||||
|
||||
self->priv->queue = g_queue_new ();
|
||||
@@ -1925,6 +1956,9 @@ set_property (GObject *object,
|
||||
case PROP_STOPBITS:
|
||||
self->priv->stopbits = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_FLOW_CONTROL:
|
||||
self->priv->flow_control = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_SEND_DELAY:
|
||||
self->priv->send_delay = g_value_get_uint64 (value);
|
||||
break;
|
||||
@@ -1964,6 +1998,9 @@ get_property (GObject *object,
|
||||
case PROP_STOPBITS:
|
||||
g_value_set_uint (value, self->priv->stopbits);
|
||||
break;
|
||||
case PROP_FLOW_CONTROL:
|
||||
g_value_set_enum (value, self->priv->flow_control);
|
||||
break;
|
||||
case PROP_SEND_DELAY:
|
||||
g_value_set_uint64 (value, self->priv->send_delay);
|
||||
break;
|
||||
@@ -2061,6 +2098,15 @@ mm_port_serial_class_init (MMPortSerialClass *klass)
|
||||
1, 2, 1,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_FLOW_CONTROL,
|
||||
g_param_spec_enum (MM_PORT_SERIAL_FLOW_CONTROL,
|
||||
"flowcontrol",
|
||||
"Select flow control (see MMFlowControl definition)",
|
||||
MM_TYPE_FLOW_CONTROL,
|
||||
MM_FLOW_CONTROL_UNKNOWN,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_SEND_DELAY,
|
||||
g_param_spec_uint64 (MM_PORT_SERIAL_SEND_DELAY,
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#define MM_PORT_SERIAL_BITS "bits"
|
||||
#define MM_PORT_SERIAL_PARITY "parity"
|
||||
#define MM_PORT_SERIAL_STOPBITS "stopbits"
|
||||
#define MM_PORT_SERIAL_FLOW_CONTROL "flowcontrol"
|
||||
#define MM_PORT_SERIAL_SEND_DELAY "send-delay"
|
||||
#define MM_PORT_SERIAL_FD "fd" /* Construct-only */
|
||||
#define MM_PORT_SERIAL_SPEW_CONTROL "spew-control" /* Construct-only */
|
||||
@@ -154,4 +155,5 @@ gboolean mm_port_serial_set_flow_control (MMPortSerial *self,
|
||||
MMFlowControl flow_control,
|
||||
GError **error);
|
||||
|
||||
MMFlowControl mm_port_serial_get_flow_control (MMPortSerial *self);
|
||||
#endif /* MM_PORT_SERIAL_H */
|
||||
|
||||
Reference in New Issue
Block a user