diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-03-25 18:30:02 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-04-18 18:08:57 +0200 |
commit | 6312753a6bfc09922cd3d2d582f7c3a1ae5f5585 (patch) | |
tree | 47277010daf266107b2ca6e1b24ed78a0d41877e /src/mm-broadband-bearer.c | |
parent | 595bd5dbe330009a04f7840d3aef2d180e848b4e (diff) |
broadband-bearer: once connected, set flow control settings
During modem initialization we detected the flow control settings
supported by the modem, and selected the best one to use from them,
notifying it to the device via AT+IFC. The device was therefore
instructed to use that flow control setting for data transmission in
the TTY (i.e. not during AT control commands).
The missing thing was to also configure ourselves our end of the
serial port with the same flow control settings when getting into data
mode. By doing it ourselves, we avoid requiring any explicit setting
in pppd for flow control; pppd can assume the flow control settings
are already the expected ones.
Worth noting that all this setup is completely ignored for TTYs
exposed directly via USB.
https://bugs.freedesktop.org/show_bug.cgi?id=100394
Diffstat (limited to 'src/mm-broadband-bearer.c')
-rw-r--r-- | src/mm-broadband-bearer.c | 125 |
1 files changed, 121 insertions, 4 deletions
diff --git a/src/mm-broadband-bearer.c b/src/mm-broadband-bearer.c index 0565eee3..ac701733 100644 --- a/src/mm-broadband-bearer.c +++ b/src/mm-broadband-bearer.c @@ -35,6 +35,7 @@ #include "mm-log.h" #include "mm-modem-helpers.h" #include "mm-port-enums-types.h" +#include "mm-helper-enums-types.h" static void async_initable_iface_init (GAsyncInitableIface *iface); @@ -48,6 +49,14 @@ typedef enum { CONNECTION_TYPE_CDMA, } ConnectionType; +enum { + PROP_0, + PROP_FLOW_CONTROL, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + struct _MMBroadbandBearerPrivate { /*-- Common stuff --*/ /* Data port used when modem is connected */ @@ -55,6 +64,9 @@ struct _MMBroadbandBearerPrivate { /* Current connection type */ ConnectionType connection_type; + /* PPP specific */ + MMFlowControl flow_control; + /*-- 3GPP specific --*/ /* CID of the PDP context */ guint cid; @@ -254,6 +266,20 @@ dial_cdma_ready (MMBaseModem *modem, return; } + /* Configure flow control to use while connected */ + if (ctx->self->priv->flow_control != MM_FLOW_CONTROL_NONE) { + gchar *flow_control_str; + + flow_control_str = mm_flow_control_build_string_from_mask (ctx->self->priv->flow_control); + mm_dbg ("[%s] Setting flow control: %s", mm_port_get_device (ctx->data), flow_control_str); + g_free (flow_control_str); + + if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (ctx->data), ctx->self->priv->flow_control, &error)) { + mm_warn ("Couldn't set flow control settings: %s", error->message); + g_clear_error (&error); + } + } + /* The ATD command has succeeded, and therefore the TTY is in data mode now. * Instead of waiting for setting the port as connected later in * connect_succeeded(), we do it right away so that we stop our polling. */ @@ -557,6 +583,8 @@ atd_ready (MMBaseModem *modem, GAsyncResult *res, Dial3gppContext *ctx) { + GError *error = NULL; + /* DO NOT check for cancellable here. If we got here without errors, the * bearer is really connected and therefore we need to reflect that in * the state machine. */ @@ -576,6 +604,20 @@ atd_ready (MMBaseModem *modem, return; } + /* Configure flow control to use while connected */ + if (ctx->self->priv->flow_control != MM_FLOW_CONTROL_NONE) { + gchar *flow_control_str; + + flow_control_str = mm_flow_control_build_string_from_mask (ctx->self->priv->flow_control); + mm_dbg ("[%s] Setting flow control: %s", mm_port_get_device (MM_PORT (ctx->dial_port)), flow_control_str); + g_free (flow_control_str); + + if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (ctx->dial_port), ctx->self->priv->flow_control, &error)) { + mm_warn ("Couldn't set flow control settings: %s", error->message); + g_clear_error (&error); + } + } + /* The ATD command has succeeded, and therefore the TTY is in data mode now. * Instead of waiting for setting the port as connected later in * connect_succeeded(), we do it right away so that we stop our polling. */ @@ -1455,6 +1497,16 @@ data_flash_cdma_ready (MMPortSerial *data, mm_port_serial_flash_finish (data, res, &error); + /* Cleanup flow control */ + if (ctx->self->priv->flow_control != MM_FLOW_CONTROL_NONE) { + GError *flow_control_error = NULL; + + if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (data), MM_FLOW_CONTROL_NONE, &flow_control_error)) { + mm_dbg ("Couldn't reset flow control settings: %s", flow_control_error->message); + g_clear_error (&flow_control_error); + } + } + /* We kept the serial port open during connection, now we close that open * count */ mm_port_serial_close (data); @@ -1572,6 +1624,16 @@ data_flash_3gpp_ready (MMPortSerial *data, mm_port_serial_flash_finish (data, res, &error); + /* Cleanup flow control */ + if (ctx->self->priv->flow_control != MM_FLOW_CONTROL_NONE) { + GError *flow_control_error = NULL; + + if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (data), MM_FLOW_CONTROL_NONE, &flow_control_error)) { + mm_dbg ("Couldn't reset flow control settings: %s", flow_control_error->message); + g_clear_error (&flow_control_error); + } + } + /* We kept the serial port open during connection, now we close that open * count */ mm_port_serial_close (data); @@ -2252,18 +2314,62 @@ mm_broadband_bearer_new (MMBroadbandModem *modem, GAsyncReadyCallback callback, gpointer user_data) { + MMFlowControl flow_control; + + /* Inherit flow control from modem object directly */ + g_object_get (modem, + MM_BROADBAND_MODEM_FLOW_CONTROL, &flow_control, + NULL); + g_async_initable_new_async ( MM_TYPE_BROADBAND_BEARER, G_PRIORITY_DEFAULT, cancellable, callback, user_data, - MM_BASE_BEARER_MODEM, modem, - MM_BASE_BEARER_CONFIG, properties, + MM_BASE_BEARER_MODEM, modem, + MM_BASE_BEARER_CONFIG, properties, + MM_BROADBAND_BEARER_FLOW_CONTROL, flow_control, NULL); } static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MMBroadbandBearer *self = MM_BROADBAND_BEARER (object); + + switch (prop_id) { + case PROP_FLOW_CONTROL: + self->priv->flow_control = g_value_get_flags (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MMBroadbandBearer *self = MM_BROADBAND_BEARER (object); + + switch (prop_id) { + case PROP_FLOW_CONTROL: + g_value_set_flags (value, self->priv->flow_control); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void mm_broadband_bearer_init (MMBroadbandBearer *self) { /* Initialize private data */ @@ -2273,6 +2379,7 @@ mm_broadband_bearer_init (MMBroadbandBearer *self) /* Set defaults */ self->priv->connection_type = CONNECTION_TYPE_NONE; + self->priv->flow_control = MM_FLOW_CONTROL_NONE; } static void @@ -2300,8 +2407,9 @@ mm_broadband_bearer_class_init (MMBroadbandBearerClass *klass) g_type_class_add_private (object_class, sizeof (MMBroadbandBearerPrivate)); - /* Virtual methods */ - object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; base_bearer_class->connect = connect; base_bearer_class->connect_finish = connect_finish; @@ -2325,4 +2433,13 @@ mm_broadband_bearer_class_init (MMBroadbandBearerClass *klass) klass->disconnect_3gpp_finish = detailed_disconnect_finish; klass->disconnect_cdma = disconnect_cdma; klass->disconnect_cdma_finish = detailed_disconnect_finish; + + properties[PROP_FLOW_CONTROL] = + g_param_spec_flags (MM_BROADBAND_BEARER_FLOW_CONTROL, + "Flow control", + "Flow control settings to use during connection", + MM_TYPE_FLOW_CONTROL, + MM_FLOW_CONTROL_NONE, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_FLOW_CONTROL, properties[PROP_FLOW_CONTROL]); } |