diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-09-10 11:44:54 +0200 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2018-09-12 17:15:46 +0000 |
commit | a9f871805b8e9b8c16a60b46ccdc525c78352f6c (patch) | |
tree | 87df861ea96baf7846c7ff1d43f2f383b552e269 | |
parent | b773e610eb68901624928b4dadb456d595a5d37c (diff) | |
download | ModemManager-a9f871805b8e9b8c16a60b46ccdc525c78352f6c.tar.gz |
broadband-modem: rework flow control selection logic
Try to simplify a bit the logic that selects the flow control to be
used during connectivity:
* We detect early if the requested flow control (via udev tags) is
actually supported by the modem (as eported by AT+IFC=?), and if it
isn't, we error out directly.
* We try to set in a single place the AT commands to be used to setup
the flow control, once we have decided which one we're going to
use.
* Use the string builder helpers to log the flow control values.
-rw-r--r-- | src/mm-broadband-modem.c | 111 |
1 files changed, 56 insertions, 55 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 1ca614971..3c5b73759 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -3311,11 +3311,13 @@ ifc_test_ready (MMBaseModem *_self, MMBroadbandModem *self; GError *error = NULL; const gchar *response; - MMFlowControl mask; const gchar *cmd; - MMFlowControl flow_control = MM_FLOW_CONTROL_UNKNOWN; + MMFlowControl flow_control_supported; + MMFlowControl flow_control_selected = MM_FLOW_CONTROL_UNKNOWN; + MMFlowControl flow_control_requested; + gchar *flow_control_supported_str = NULL; + gchar *flow_control_selected_str = NULL; MMPortSerialAt *port; - const gchar *err_str = NULL; self = MM_BROADBAND_MODEM (_self); @@ -3325,75 +3327,79 @@ ifc_test_ready (MMBaseModem *_self, goto out; /* Parse response */ - mask = mm_parse_ifc_test_response (response, &error); - if (mask == MM_FLOW_CONTROL_UNKNOWN) + flow_control_supported = mm_parse_ifc_test_response (response, &error); + if (flow_control_supported == MM_FLOW_CONTROL_UNKNOWN) goto out; + flow_control_supported_str = mm_flow_control_build_string_from_mask (flow_control_supported); port = mm_base_modem_peek_best_at_port (_self, &error); if (!port) goto out; - flow_control = mm_port_serial_get_flow_control (MM_PORT_SERIAL (port)); + flow_control_requested = mm_port_serial_get_flow_control (MM_PORT_SERIAL (port)); + if (flow_control_requested != MM_FLOW_CONTROL_UNKNOWN) { + gchar *flow_control_requested_str; - switch (flow_control) { - case MM_FLOW_CONTROL_RTS_CTS: - if (mask & MM_FLOW_CONTROL_RTS_CTS) { - self->priv->flow_control = MM_FLOW_CONTROL_RTS_CTS; - cmd = "+IFC=2,2"; - } else - err_str = "RTS/CTS"; - break; - case MM_FLOW_CONTROL_XON_XOFF: - if (mask & MM_FLOW_CONTROL_XON_XOFF) { - self->priv->flow_control = MM_FLOW_CONTROL_XON_XOFF; - cmd = "+IFC=1,1"; - } else - err_str = "xon/xoff"; - break; - case MM_FLOW_CONTROL_NONE: - if (mask & MM_FLOW_CONTROL_NONE) { - self->priv->flow_control = MM_FLOW_CONTROL_NONE; - cmd = "+IFC=0,0"; - } else - err_str = "none"; - break; - case MM_FLOW_CONTROL_UNKNOWN: + flow_control_requested_str = mm_flow_control_build_string_from_mask (flow_control_requested); + + /* If flow control settings requested via udev tag are not supported by + * the modem, we trigger a fatal error */ + if (!(flow_control_supported & flow_control_requested)) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, + "Explicitly requested flow control settings (%s) are not supported by the device (%s)", + flow_control_requested_str, flow_control_supported_str); + g_object_unref (task); + g_free (flow_control_requested_str); + g_free (flow_control_supported_str); + return; + } + + mm_dbg ("Flow control settings explicitly requested (%s)", flow_control_requested_str); + flow_control_selected = flow_control_requested; + flow_control_selected_str = flow_control_requested_str; + } else { /* If flow control is not set explicitly by udev tags, * we prefer the methods in this order: * RTS/CTS * XON/XOFF * None. */ - if (mask & MM_FLOW_CONTROL_RTS_CTS) { - self->priv->flow_control = MM_FLOW_CONTROL_RTS_CTS; - cmd = "+IFC=2,2"; - } else if (mask & MM_FLOW_CONTROL_XON_XOFF) { - self->priv->flow_control = MM_FLOW_CONTROL_XON_XOFF; - cmd = "+IFC=1,1"; - } else if (mask & MM_FLOW_CONTROL_NONE) { - self->priv->flow_control = MM_FLOW_CONTROL_NONE; - cmd = "+IFC=0,0"; - } else + if (flow_control_supported & MM_FLOW_CONTROL_RTS_CTS) + flow_control_selected = MM_FLOW_CONTROL_RTS_CTS; + else if (flow_control_supported & MM_FLOW_CONTROL_XON_XOFF) + flow_control_selected = MM_FLOW_CONTROL_XON_XOFF; + else if (flow_control_supported & MM_FLOW_CONTROL_NONE) + flow_control_selected = MM_FLOW_CONTROL_NONE; + else g_assert_not_reached (); - break; + flow_control_selected_str = mm_flow_control_build_string_from_mask (flow_control_selected); + mm_dbg ("Flow control settings automatically selected (%s)", flow_control_selected_str); } - if (err_str) { - g_set_error (&error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "%s: failed to set serial flow control to %s", - __func__, err_str); - goto fatal; - } - - /* Notify the flow control property update */ + /* Select flow control for all connections */ + self->priv->flow_control = flow_control_selected; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FLOW_CONTROL]); /* Set flow control settings and ignore result */ + switch (flow_control_selected) { + case MM_FLOW_CONTROL_RTS_CTS: + cmd = "+IFC=2,2"; + break; + case MM_FLOW_CONTROL_XON_XOFF: + cmd = "+IFC=1,1"; + break; + case MM_FLOW_CONTROL_NONE: + cmd = "+IFC=0,0"; + break; + default: + g_assert_not_reached (); + } mm_base_modem_at_command (_self, cmd, 3, FALSE, NULL, NULL); out: + g_free (flow_control_supported_str); + g_free (flow_control_selected_str); + /* Ignore errors */ if (error) { mm_dbg ("couldn't load supported flow control methods: %s", error->message); @@ -3402,11 +3408,6 @@ out: g_task_return_boolean (task, TRUE); g_object_unref (task); - return; - -fatal: - g_task_return_error (task, error); - g_object_unref (task); } static void |