modemmanager: update revision to get flow control patches from repo
The flow control patches have been merged to the master branch, so
update the revision to remove those patches from our layer.
This reverts commit a7c51af5b8.
Signed-off-by: Javier Viguera <javier.viguera@digi.com>
This commit is contained in:
parent
3d45a10ead
commit
3de76b2eae
|
|
@ -1,290 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 00:47:50 +0100
|
|
||||||
Subject: [PATCH] =?UTF-8?q?helpers:=20new=20parser=20for=20AT+IFC=3D=3F?=
|
|
||||||
|
|
||||||
Instead of having the parser return separate list of supported flow
|
|
||||||
controls for TE and TA, we simplify it by only returning those
|
|
||||||
settings that apply to both TE and TA.
|
|
||||||
|
|
||||||
This logic isn't perfect either, though, as some settings (e.g. '3' in
|
|
||||||
TE in some modems, specifying a different XON/XOFF behavior) may not
|
|
||||||
have a corresponding setting in the other end.
|
|
||||||
|
|
||||||
The most common cases we care about (i.e. standard XON/XOFF, RTS/CTS)
|
|
||||||
should be properly reported with this logic.
|
|
||||||
---
|
|
||||||
src/mm-modem-helpers.c | 113 +++++++++++++++++++++++++++++++++++++++++
|
|
||||||
src/mm-modem-helpers.h | 17 +++++++
|
|
||||||
src/tests/test-modem-helpers.c | 100 ++++++++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 230 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
|
|
||||||
index b45561768077..679f925281a3 100644
|
|
||||||
--- a/src/mm-modem-helpers.c
|
|
||||||
+++ b/src/mm-modem-helpers.c
|
|
||||||
@@ -525,6 +525,119 @@ mm_voice_clip_regex_get (void)
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
+static MMFlowControl
|
|
||||||
+flow_control_array_to_mask (GArray *array,
|
|
||||||
+ const gchar *item)
|
|
||||||
+{
|
|
||||||
+ MMFlowControl mask = MM_FLOW_CONTROL_UNKNOWN;
|
|
||||||
+ guint i;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < array->len; i++) {
|
|
||||||
+ guint mode;
|
|
||||||
+
|
|
||||||
+ mode = g_array_index (array, guint, i);
|
|
||||||
+ switch (mode) {
|
|
||||||
+ case 0:
|
|
||||||
+ mm_dbg ("%s supports no flow control", item);
|
|
||||||
+ mask |= MM_FLOW_CONTROL_NONE;
|
|
||||||
+ break;
|
|
||||||
+ case 1:
|
|
||||||
+ mm_dbg ("%s supports XON/XOFF flow control", item);
|
|
||||||
+ mask |= MM_FLOW_CONTROL_XON_XOFF;
|
|
||||||
+ break;
|
|
||||||
+ case 2:
|
|
||||||
+ mm_dbg ("%s supports RTS/CTS flow control", item);
|
|
||||||
+ mask |= MM_FLOW_CONTROL_RTS_CTS;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return mask;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static MMFlowControl
|
|
||||||
+flow_control_match_info_to_mask (GMatchInfo *match_info,
|
|
||||||
+ guint index,
|
|
||||||
+ const gchar *item,
|
|
||||||
+ GError **error)
|
|
||||||
+{
|
|
||||||
+ MMFlowControl mask = MM_FLOW_CONTROL_UNKNOWN;
|
|
||||||
+ gchar *aux = NULL;
|
|
||||||
+ GArray *array = NULL;
|
|
||||||
+
|
|
||||||
+ if (!(aux = mm_get_string_unquoted_from_match_info (match_info, index))) {
|
|
||||||
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
|
||||||
+ "Error retrieving list of supported %s flow control methods", item);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!(array = mm_parse_uint_list (aux, error))) {
|
|
||||||
+ g_prefix_error (error, "Error parsing list of supported %s flow control methods: ", item);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((mask = flow_control_array_to_mask (array, item)) == MM_FLOW_CONTROL_UNKNOWN) {
|
|
||||||
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
|
||||||
+ "No known %s flow control method given", item);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+out:
|
|
||||||
+ g_clear_pointer (&aux, g_free);
|
|
||||||
+ g_clear_pointer (&array, g_array_unref);
|
|
||||||
+
|
|
||||||
+ return mask;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+MMFlowControl
|
|
||||||
+mm_parse_ifc_test_response (const gchar *response,
|
|
||||||
+ GError **error)
|
|
||||||
+{
|
|
||||||
+ GRegex *r;
|
|
||||||
+ GError *inner_error = NULL;
|
|
||||||
+ GMatchInfo *match_info = NULL;
|
|
||||||
+ MMFlowControl te_mask = MM_FLOW_CONTROL_UNKNOWN;
|
|
||||||
+ MMFlowControl ta_mask = MM_FLOW_CONTROL_UNKNOWN;
|
|
||||||
+ MMFlowControl mask = MM_FLOW_CONTROL_UNKNOWN;
|
|
||||||
+
|
|
||||||
+ r = g_regex_new ("(?:\\+IFC:)?\\s*\\((.*)\\),\\((.*)\\)(?:\\r\\n)?", 0, 0, NULL);
|
|
||||||
+ g_assert (r != NULL);
|
|
||||||
+
|
|
||||||
+ g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
|
|
||||||
+ if (inner_error)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ if (!g_match_info_matches (match_info)) {
|
|
||||||
+ inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match response");
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Parse TE flow control methods */
|
|
||||||
+ if ((te_mask = flow_control_match_info_to_mask (match_info, 1, "TE", &inner_error)) == MM_FLOW_CONTROL_UNKNOWN)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ /* Parse TA flow control methods */
|
|
||||||
+ if ((ta_mask = flow_control_match_info_to_mask (match_info, 2, "TA", &inner_error)) == MM_FLOW_CONTROL_UNKNOWN)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ /* Only those methods in both TA and TE will be the ones we report */
|
|
||||||
+ mask = te_mask & ta_mask;
|
|
||||||
+
|
|
||||||
+out:
|
|
||||||
+
|
|
||||||
+ g_clear_pointer (&match_info, g_match_info_free);
|
|
||||||
+ g_regex_unref (r);
|
|
||||||
+
|
|
||||||
+ if (inner_error)
|
|
||||||
+ g_propagate_error (error, inner_error);
|
|
||||||
+
|
|
||||||
+ return mask;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*************************************************************************/
|
|
||||||
+
|
|
||||||
/* +CREG: <stat> (GSM 07.07 CREG=1 unsolicited) */
|
|
||||||
#define CREG1 "\\+(CREG|CGREG|CEREG):\\s*0*([0-9])"
|
|
||||||
|
|
||||||
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
|
|
||||||
index a74924e353ad..bd10b940d1a4 100644
|
|
||||||
--- a/src/mm-modem-helpers.h
|
|
||||||
+++ b/src/mm-modem-helpers.h
|
|
||||||
@@ -95,6 +95,23 @@ GRegex *mm_voice_cring_regex_get(void);
|
|
||||||
GRegex *mm_voice_clip_regex_get (void);
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
+/* SERIAL specific helpers and utilities */
|
|
||||||
+
|
|
||||||
+/* AT+IFC=? response parser.
|
|
||||||
+ * For simplicity, we'll only consider flow control methods available in both
|
|
||||||
+ * TE and TA. */
|
|
||||||
+
|
|
||||||
+typedef enum {
|
|
||||||
+ MM_FLOW_CONTROL_UNKNOWN = 0,
|
|
||||||
+ MM_FLOW_CONTROL_NONE = 1 << 0, /* IFC=0,0 */
|
|
||||||
+ MM_FLOW_CONTROL_XON_XOFF = 1 << 1, /* IFC=1,1 */
|
|
||||||
+ MM_FLOW_CONTROL_RTS_CTS = 1 << 2, /* IFC=2,2 */
|
|
||||||
+} MMFlowControl;
|
|
||||||
+
|
|
||||||
+MMFlowControl mm_parse_ifc_test_response (const gchar *response,
|
|
||||||
+ GError **error);
|
|
||||||
+
|
|
||||||
+/*****************************************************************************/
|
|
||||||
/* 3GPP specific helpers and utilities */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
|
|
||||||
index ae0eec99f969..b59c5900a832 100644
|
|
||||||
--- a/src/tests/test-modem-helpers.c
|
|
||||||
+++ b/src/tests/test-modem-helpers.c
|
|
||||||
@@ -33,6 +33,93 @@
|
|
||||||
g_assert_cmpfloat (fabs (val1 - val2), <, tolerance)
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
+/* Test IFC=? responses */
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response (const gchar *str,
|
|
||||||
+ const MMFlowControl expected)
|
|
||||||
+{
|
|
||||||
+ MMFlowControl mask;
|
|
||||||
+ GError *error = NULL;
|
|
||||||
+
|
|
||||||
+ mask = mm_parse_ifc_test_response (str, &error);
|
|
||||||
+ g_assert_no_error (error);
|
|
||||||
+ g_assert_cmpuint (mask, ==, expected);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_all_simple (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0,1,2),(0,1,2)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_XON_XOFF | MM_FLOW_CONTROL_RTS_CTS));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_all_groups (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0-2),(0-2)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_XON_XOFF | MM_FLOW_CONTROL_RTS_CTS));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_none_only (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0),(0)", MM_FLOW_CONTROL_NONE);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_xon_xoff_only (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (1),(1)", MM_FLOW_CONTROL_XON_XOFF);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_rts_cts_only (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (2),(2)", MM_FLOW_CONTROL_RTS_CTS);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_no_xon_xoff (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0,2),(0,2)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_RTS_CTS));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_no_xon_xoff_in_ta (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0,1,2),(0,2)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_RTS_CTS));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_no_xon_xoff_in_te (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0,2),(0,1,2)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_RTS_CTS));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_no_rts_cts_simple (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0,1),(0,1)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_XON_XOFF));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_no_rts_cts_groups (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0-1),(0-1)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_XON_XOFF));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_all_simple_and_unknown (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0,1,2,3),(0,1,2)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_XON_XOFF | MM_FLOW_CONTROL_RTS_CTS));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_ifc_response_all_groups_and_unknown (void)
|
|
||||||
+{
|
|
||||||
+ test_ifc_response ("+IFC (0-3),(0-2)", (MM_FLOW_CONTROL_NONE | MM_FLOW_CONTROL_XON_XOFF | MM_FLOW_CONTROL_RTS_CTS));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*****************************************************************************/
|
|
||||||
/* Test WS46=? responses */
|
|
||||||
|
|
||||||
static void
|
|
||||||
@@ -3536,6 +3623,19 @@ int main (int argc, char **argv)
|
|
||||||
suite = g_test_get_root ();
|
|
||||||
reg_data = reg_test_data_new ();
|
|
||||||
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_all_simple, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_all_groups, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_none_only, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_xon_xoff_only, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_rts_cts_only, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_no_xon_xoff, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_no_xon_xoff_in_ta, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_no_xon_xoff_in_te, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_no_rts_cts_simple, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_no_rts_cts_groups, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_all_simple_and_unknown, NULL));
|
|
||||||
+ g_test_suite_add (suite, TESTCASE (test_ifc_response_all_groups_and_unknown, NULL));
|
|
||||||
+
|
|
||||||
g_test_suite_add (suite, TESTCASE (test_ws46_response_generic_2g3g4g, NULL));
|
|
||||||
g_test_suite_add (suite, TESTCASE (test_ws46_response_generic_2g3g, NULL));
|
|
||||||
g_test_suite_add (suite, TESTCASE (test_ws46_response_generic_2g3g_v2, NULL));
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 01:11:45 +0100
|
|
||||||
Subject: [PATCH] broadband-modem: query supported flow control modes before
|
|
||||||
setting
|
|
||||||
|
|
||||||
Instead of assuming XON/XOFF is supported, we query the supported flow
|
|
||||||
control modes, and then we set the best one based on that, preferring
|
|
||||||
hardware flow control over software flow control.
|
|
||||||
---
|
|
||||||
src/mm-broadband-modem.c | 79 ++++++++++++++++++++++++++++++++++++------------
|
|
||||||
1 file changed, 60 insertions(+), 19 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
|
|
||||||
index 97a268a2eb81..e5ad354882bb 100644
|
|
||||||
--- a/src/mm-broadband-modem.c
|
|
||||||
+++ b/src/mm-broadband-modem.c
|
|
||||||
@@ -3093,12 +3093,59 @@ modem_load_supported_charsets (MMIfaceModem *self,
|
|
||||||
/* configuring flow control (Modem interface) */
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
-modem_setup_flow_control_finish (MMIfaceModem *self,
|
|
||||||
- GAsyncResult *res,
|
|
||||||
- GError **error)
|
|
||||||
+modem_setup_flow_control_finish (MMIfaceModem *self,
|
|
||||||
+ GAsyncResult *res,
|
|
||||||
+ GError **error)
|
|
||||||
{
|
|
||||||
- /* Completely ignore errors */
|
|
||||||
- return TRUE;
|
|
||||||
+ return g_task_propagate_boolean (G_TASK (res), error);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+ifc_test_ready (MMBaseModem *self,
|
|
||||||
+ GAsyncResult *res,
|
|
||||||
+ GTask *task)
|
|
||||||
+{
|
|
||||||
+ GError *error = NULL;
|
|
||||||
+ const gchar *response;
|
|
||||||
+ MMFlowControl mask;
|
|
||||||
+ const gchar *cmd;
|
|
||||||
+
|
|
||||||
+ /* Completely ignore errors in AT+IFC=? */
|
|
||||||
+ response = mm_base_modem_at_command_finish (self, res, &error);
|
|
||||||
+ if (!response)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ /* Parse response */
|
|
||||||
+ mask = mm_parse_ifc_test_response (response, &error);
|
|
||||||
+ if (mask == MM_FLOW_CONTROL_UNKNOWN)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ /* We prefer the methods in this order:
|
|
||||||
+ * RTS/CTS
|
|
||||||
+ * XON/XOFF
|
|
||||||
+ * None.
|
|
||||||
+ */
|
|
||||||
+ if (mask & MM_FLOW_CONTROL_RTS_CTS)
|
|
||||||
+ cmd = "+IFC=2,2";
|
|
||||||
+ else if (mask & MM_FLOW_CONTROL_XON_XOFF)
|
|
||||||
+ cmd = "+IFC=1,1";
|
|
||||||
+ else if (mask & MM_FLOW_CONTROL_NONE)
|
|
||||||
+ cmd = "+IFC=0,0";
|
|
||||||
+ else
|
|
||||||
+ g_assert_not_reached ();
|
|
||||||
+
|
|
||||||
+ /* Set flow control settings and ignore result */
|
|
||||||
+ mm_base_modem_at_command (self, cmd, 3, FALSE, NULL, NULL);
|
|
||||||
+
|
|
||||||
+out:
|
|
||||||
+ /* Ignore errors */
|
|
||||||
+ if (error) {
|
|
||||||
+ mm_dbg ("couldn't load supported flow control methods: %s", error->message);
|
|
||||||
+ g_error_free (error);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ g_task_return_boolean (task, TRUE);
|
|
||||||
+ g_object_unref (task);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
@@ -3106,23 +3153,17 @@ modem_setup_flow_control (MMIfaceModem *self,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
- GSimpleAsyncResult *result;
|
|
||||||
+ GTask *task;
|
|
||||||
+
|
|
||||||
+ task = g_task_new (self, NULL, callback, user_data);
|
|
||||||
|
|
||||||
- /* By default, try to set XOFF/XON flow control */
|
|
||||||
+ /* Query supported flow control methods */
|
|
||||||
mm_base_modem_at_command (MM_BASE_MODEM (self),
|
|
||||||
- "+IFC=1,1",
|
|
||||||
+ "+IFC=?",
|
|
||||||
3,
|
|
||||||
- FALSE,
|
|
||||||
- NULL,
|
|
||||||
- NULL);
|
|
||||||
-
|
|
||||||
- result = g_simple_async_result_new (G_OBJECT (self),
|
|
||||||
- callback,
|
|
||||||
- user_data,
|
|
||||||
- modem_setup_flow_control);
|
|
||||||
- g_simple_async_result_set_op_res_gboolean (result, TRUE);
|
|
||||||
- g_simple_async_result_complete_in_idle (result);
|
|
||||||
- g_object_unref (result);
|
|
||||||
+ TRUE,
|
|
||||||
+ (GAsyncReadyCallback)ifc_test_ready,
|
|
||||||
+ task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 01:14:45 +0100
|
|
||||||
Subject: [PATCH] wavecom: ignore custom flow control handling
|
|
||||||
|
|
||||||
The generic modem object already supports querying for the supported
|
|
||||||
methods and setting the best one found.
|
|
||||||
---
|
|
||||||
plugins/wavecom/mm-broadband-modem-wavecom.c | 27 ---------------------------
|
|
||||||
1 file changed, 27 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/plugins/wavecom/mm-broadband-modem-wavecom.c b/plugins/wavecom/mm-broadband-modem-wavecom.c
|
|
||||||
index 47c6b4f040a0..0e93e47ec701 100644
|
|
||||||
--- a/plugins/wavecom/mm-broadband-modem-wavecom.c
|
|
||||||
+++ b/plugins/wavecom/mm-broadband-modem-wavecom.c
|
|
||||||
@@ -1242,31 +1242,6 @@ modem_after_sim_unlock (MMIfaceModem *self,
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
-/* Flow control (Modem interface) */
|
|
||||||
-
|
|
||||||
-static gboolean
|
|
||||||
-setup_flow_control_finish (MMIfaceModem *self,
|
|
||||||
- GAsyncResult *res,
|
|
||||||
- GError **error)
|
|
||||||
-{
|
|
||||||
- return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static void
|
|
||||||
-setup_flow_control (MMIfaceModem *self,
|
|
||||||
- GAsyncReadyCallback callback,
|
|
||||||
- gpointer user_data)
|
|
||||||
-{
|
|
||||||
- /* Wavecom doesn't have XOFF/XON flow control, so we enable RTS/CTS */
|
|
||||||
- mm_base_modem_at_command (MM_BASE_MODEM (self),
|
|
||||||
- "+IFC=2,2",
|
|
||||||
- 3,
|
|
||||||
- FALSE,
|
|
||||||
- callback,
|
|
||||||
- user_data);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-/*****************************************************************************/
|
|
||||||
/* Modem power up (Modem interface) */
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
@@ -1420,8 +1395,6 @@ iface_modem_init (MMIfaceModem *iface)
|
|
||||||
iface->load_access_technologies_finish = load_access_technologies_finish;
|
|
||||||
iface->modem_after_sim_unlock = modem_after_sim_unlock;
|
|
||||||
iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish;
|
|
||||||
- iface->setup_flow_control = setup_flow_control;
|
|
||||||
- iface->setup_flow_control_finish = setup_flow_control_finish;
|
|
||||||
iface->modem_power_up = modem_power_up;
|
|
||||||
iface->modem_power_up_finish = modem_power_up_finish;
|
|
||||||
iface->modem_power_down = modem_power_down;
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 01:16:25 +0100
|
|
||||||
Subject: [PATCH] telit: ignore custom flow control handling
|
|
||||||
|
|
||||||
The generic modem object already supports querying for the supported
|
|
||||||
methods and setting the best one found.
|
|
||||||
---
|
|
||||||
plugins/telit/mm-broadband-modem-telit.c | 48 --------------------------------
|
|
||||||
1 file changed, 48 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c
|
|
||||||
index 8b8731062966..cce02298352b 100644
|
|
||||||
--- a/plugins/telit/mm-broadband-modem-telit.c
|
|
||||||
+++ b/plugins/telit/mm-broadband-modem-telit.c
|
|
||||||
@@ -885,52 +885,6 @@ load_access_technologies (MMIfaceModem *self,
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
-/* Flow control (Modem interface) */
|
|
||||||
-
|
|
||||||
-static gboolean
|
|
||||||
-setup_flow_control_finish (MMIfaceModem *self,
|
|
||||||
- GAsyncResult *res,
|
|
||||||
- GError **error)
|
|
||||||
-{
|
|
||||||
- /* Completely ignore errors */
|
|
||||||
- return TRUE;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static void
|
|
||||||
-setup_flow_control (MMIfaceModem *self,
|
|
||||||
- GAsyncReadyCallback callback,
|
|
||||||
- gpointer user_data)
|
|
||||||
-{
|
|
||||||
- GSimpleAsyncResult *result;
|
|
||||||
- gchar *cmd;
|
|
||||||
- guint flow_control = 1; /* Default flow control: XON/XOFF */
|
|
||||||
-
|
|
||||||
- switch (mm_base_modem_get_product_id (MM_BASE_MODEM (self)) & 0xFFFF) {
|
|
||||||
- case 0x0021:
|
|
||||||
- flow_control = 2; /* Telit IMC modems support only RTS/CTS mode */
|
|
||||||
- break;
|
|
||||||
- default:
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- cmd = g_strdup_printf ("+IFC=%u,%u", flow_control, flow_control);
|
|
||||||
- mm_base_modem_at_command (MM_BASE_MODEM (self),
|
|
||||||
- cmd,
|
|
||||||
- 3,
|
|
||||||
- FALSE,
|
|
||||||
- NULL,
|
|
||||||
- NULL);
|
|
||||||
- result = g_simple_async_result_new (G_OBJECT (self),
|
|
||||||
- callback,
|
|
||||||
- user_data,
|
|
||||||
- setup_flow_control);
|
|
||||||
- g_simple_async_result_set_op_res_gboolean (result, TRUE);
|
|
||||||
- g_simple_async_result_complete_in_idle (result);
|
|
||||||
- g_object_unref (result);
|
|
||||||
- g_free (cmd);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-/*****************************************************************************/
|
|
||||||
/* Load current mode (Modem interface) */
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
@@ -1287,8 +1241,6 @@ iface_modem_init (MMIfaceModem *iface)
|
|
||||||
iface->modem_power_down_finish = modem_power_down_finish;
|
|
||||||
iface->load_access_technologies = load_access_technologies;
|
|
||||||
iface->load_access_technologies_finish = load_access_technologies_finish;
|
|
||||||
- iface->setup_flow_control = setup_flow_control;
|
|
||||||
- iface->setup_flow_control_finish = setup_flow_control_finish;
|
|
||||||
iface->load_supported_modes = load_supported_modes;
|
|
||||||
iface->load_supported_modes_finish = load_supported_modes_finish;
|
|
||||||
iface->load_current_modes = load_current_modes;
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 18:17:41 +0100
|
|
||||||
Subject: [PATCH] port-serial: new internal method to run tcsetattr()
|
|
||||||
|
|
||||||
The method takes care of looping if EAGAIN errors happen, as well as
|
|
||||||
checking whether all attributes were set or not.
|
|
||||||
---
|
|
||||||
src/mm-port-serial.c | 119 ++++++++++++++++++++++++---------------------------
|
|
||||||
1 file changed, 57 insertions(+), 62 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/mm-port-serial.c b/src/mm-port-serial.c
|
|
||||||
index 2b6b92d3d1da..f2b97a02486d 100644
|
|
||||||
--- a/src/mm-port-serial.c
|
|
||||||
+++ b/src/mm-port-serial.c
|
|
||||||
@@ -347,9 +347,62 @@ parse_stopbits (guint i)
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
+internal_tcsetattr (MMPortSerial *self,
|
|
||||||
+ gint fd,
|
|
||||||
+ const struct termios *options,
|
|
||||||
+ GError **error)
|
|
||||||
+{
|
|
||||||
+ guint count;
|
|
||||||
+ struct termios other;
|
|
||||||
+
|
|
||||||
+#define MAX_TCSETATTR_RETRIES 4
|
|
||||||
+
|
|
||||||
+ for (count = 0; count < MAX_TCSETATTR_RETRIES; count++) {
|
|
||||||
+ /* try to set the new port attributes */
|
|
||||||
+ errno = 0;
|
|
||||||
+ if (tcsetattr (fd, TCSANOW, options) == 0)
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ /* hard error if not EAGAIN */
|
|
||||||
+ if (errno != EAGAIN) {
|
|
||||||
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
|
||||||
+ "couldn't set serial port attributes: %s", g_strerror (errno));
|
|
||||||
+ return FALSE;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* try a few times if EAGAIN */
|
|
||||||
+ g_usleep (100000);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* too many retries? */
|
|
||||||
+ if (count == MAX_TCSETATTR_RETRIES) {
|
|
||||||
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
|
||||||
+ "couldn't set serial port attributes: too many retries (%u)", count);
|
|
||||||
+ return FALSE;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* tcsetattr() returns 0 if any of the requested attributes could be set,
|
|
||||||
+ * so we should double-check that all were set and log if not. Just with
|
|
||||||
+ * debug level, as we're ignoring this issue all together anyway.
|
|
||||||
+ */
|
|
||||||
+ memset (&other, 0, sizeof (struct termios));
|
|
||||||
+ errno = 0;
|
|
||||||
+ if (tcgetattr (fd, &other) != 0)
|
|
||||||
+ mm_dbg ("(%s): couldn't get serial port attributes after setting them: %s",
|
|
||||||
+ mm_port_get_device (MM_PORT (self)), g_strerror (errno));
|
|
||||||
+ else if (memcmp (options, &other, sizeof (struct termios)) != 0)
|
|
||||||
+ mm_dbg ("(%s): port attributes not fully set",
|
|
||||||
+ mm_port_get_device (MM_PORT (self)));
|
|
||||||
+
|
|
||||||
+#undef MAX_TCSETATTR_RETRIES
|
|
||||||
+
|
|
||||||
+ return TRUE;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static gboolean
|
|
||||||
real_config_fd (MMPortSerial *self, int fd, GError **error)
|
|
||||||
{
|
|
||||||
- struct termios stbuf, other;
|
|
||||||
+ struct termios stbuf;
|
|
||||||
guint speed;
|
|
||||||
gint bits;
|
|
||||||
gint parity;
|
|
||||||
@@ -416,32 +469,7 @@ real_config_fd (MMPortSerial *self, int fd, GError **error)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (tcsetattr (fd, TCSANOW, &stbuf) < 0) {
|
|
||||||
- g_set_error (error,
|
|
||||||
- MM_CORE_ERROR,
|
|
||||||
- MM_CORE_ERROR_FAILED,
|
|
||||||
- "%s: failed to set serial port attributes; errno %d",
|
|
||||||
- __func__, errno);
|
|
||||||
- return FALSE;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* tcsetattr() returns 0 if any of the requested attributes could be set,
|
|
||||||
- * so we should double-check that all were set and log a warning if not.
|
|
||||||
- */
|
|
||||||
- memset (&other, 0, sizeof (struct termios));
|
|
||||||
- errno = 0;
|
|
||||||
- if (tcgetattr (fd, &other) != 0) {
|
|
||||||
- mm_warn ("(%s): tcgetattr() error: %d",
|
|
||||||
- mm_port_get_device (MM_PORT (self)),
|
|
||||||
- errno);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (memcmp (&stbuf, &other, sizeof (other)) != 0) {
|
|
||||||
- mm_warn ("(%s): port attributes not fully set",
|
|
||||||
- mm_port_get_device (MM_PORT (self)));
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return TRUE;
|
|
||||||
+ return internal_tcsetattr (self, fd, &stbuf, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
@@ -1576,15 +1604,11 @@ static gboolean
|
|
||||||
set_speed (MMPortSerial *self, speed_t speed, GError **error)
|
|
||||||
{
|
|
||||||
struct termios options;
|
|
||||||
- int fd, count = 4;
|
|
||||||
- gboolean success = FALSE;
|
|
||||||
|
|
||||||
g_assert (self->priv->fd >= 0);
|
|
||||||
|
|
||||||
- fd = self->priv->fd;
|
|
||||||
-
|
|
||||||
memset (&options, 0, sizeof (struct termios));
|
|
||||||
- if (tcgetattr (fd, &options) != 0) {
|
|
||||||
+ if (tcgetattr (self->priv->fd, &options) != 0) {
|
|
||||||
g_set_error (error,
|
|
||||||
MM_CORE_ERROR,
|
|
||||||
MM_CORE_ERROR_FAILED,
|
|
||||||
@@ -1601,36 +1625,7 @@ set_speed (MMPortSerial *self, speed_t speed, GError **error)
|
|
||||||
if (self->priv->rts_cts)
|
|
||||||
options.c_cflag |= (CRTSCTS);
|
|
||||||
|
|
||||||
- while (count-- > 0) {
|
|
||||||
- if (tcsetattr (fd, TCSANOW, &options) == 0) {
|
|
||||||
- success = TRUE;
|
|
||||||
- break; /* Operation successful */
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* Try a few times if EAGAIN */
|
|
||||||
- if (errno == EAGAIN)
|
|
||||||
- g_usleep (100000);
|
|
||||||
- else {
|
|
||||||
- /* If not EAGAIN, hard error */
|
|
||||||
- g_set_error (error,
|
|
||||||
- MM_CORE_ERROR,
|
|
||||||
- MM_CORE_ERROR_FAILED,
|
|
||||||
- "%s: tcsetattr() error %d",
|
|
||||||
- __func__, errno);
|
|
||||||
- return FALSE;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (!success) {
|
|
||||||
- g_set_error (error,
|
|
||||||
- MM_CORE_ERROR,
|
|
||||||
- MM_CORE_ERROR_FAILED,
|
|
||||||
- "%s: tcsetattr() retry timeout",
|
|
||||||
- __func__);
|
|
||||||
- return FALSE;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return TRUE;
|
|
||||||
+ return internal_tcsetattr (self, self->priv->fd, &options, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 18:18:46 +0100
|
|
||||||
Subject: [PATCH] port-serial: new method to explicitly set flow control
|
|
||||||
settings
|
|
||||||
|
|
||||||
---
|
|
||||||
src/mm-port-serial.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
src/mm-port-serial.h | 5 +++++
|
|
||||||
2 files changed, 55 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/mm-port-serial.c b/src/mm-port-serial.c
|
|
||||||
index f2b97a02486d..e55f90625020 100644
|
|
||||||
--- a/src/mm-port-serial.c
|
|
||||||
+++ b/src/mm-port-serial.c
|
|
||||||
@@ -1778,6 +1778,56 @@ mm_port_serial_flash (MMPortSerial *self,
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
+gboolean
|
|
||||||
+mm_port_serial_set_flow_control (MMPortSerial *self,
|
|
||||||
+ MMFlowControl flow_control,
|
|
||||||
+ GError **error)
|
|
||||||
+{
|
|
||||||
+ struct termios options;
|
|
||||||
+ gboolean had_xon_xoff;
|
|
||||||
+ gboolean had_rts_cts;
|
|
||||||
+
|
|
||||||
+ /* retrieve current settings */
|
|
||||||
+ memset (&options, 0, sizeof (struct termios));
|
|
||||||
+ if (tcgetattr (self->priv->fd, &options) != 0) {
|
|
||||||
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
|
||||||
+ "couldn't get serial port attributes: %s", g_strerror (errno));
|
|
||||||
+ 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 internal_tcsetattr (self, self->priv->fd, &options, error);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*****************************************************************************/
|
|
||||||
+
|
|
||||||
MMPortSerial *
|
|
||||||
mm_port_serial_new (const char *name, MMPortType ptype)
|
|
||||||
{
|
|
||||||
diff --git a/src/mm-port-serial.h b/src/mm-port-serial.h
|
|
||||||
index 708e39123412..223b9ce1c4a4 100644
|
|
||||||
--- a/src/mm-port-serial.h
|
|
||||||
+++ b/src/mm-port-serial.h
|
|
||||||
@@ -21,6 +21,7 @@
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <gio/gio.h>
|
|
||||||
|
|
||||||
+#include "mm-modem-helpers.h"
|
|
||||||
#include "mm-port.h"
|
|
||||||
|
|
||||||
#define MM_TYPE_PORT_SERIAL (mm_port_serial_get_type ())
|
|
||||||
@@ -150,4 +151,8 @@ GByteArray *mm_port_serial_command_finish (MMPortSerial *self,
|
|
||||||
GAsyncResult *res,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
+gboolean mm_port_serial_set_flow_control (MMPortSerial *self,
|
|
||||||
+ MMFlowControl flow_control,
|
|
||||||
+ GError **error);
|
|
||||||
+
|
|
||||||
#endif /* MM_PORT_SERIAL_H */
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 18:27:09 +0100
|
|
||||||
Subject: [PATCH] port-serial: remove all default flow control settings
|
|
||||||
|
|
||||||
We won't set XON/XOFF by default and we won't allow setting RTS/CTS
|
|
||||||
via a property. The serial port by default starts with no flow control
|
|
||||||
configured.
|
|
||||||
---
|
|
||||||
src/mm-port-serial.c | 34 ++++++----------------------------
|
|
||||||
src/mm-port-serial.h | 1 -
|
|
||||||
2 files changed, 6 insertions(+), 29 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/mm-port-serial.c b/src/mm-port-serial.c
|
|
||||||
index e55f90625020..04ab17fe1675 100644
|
|
||||||
--- a/src/mm-port-serial.c
|
|
||||||
+++ b/src/mm-port-serial.c
|
|
||||||
@@ -56,7 +56,6 @@ enum {
|
|
||||||
PROP_SEND_DELAY,
|
|
||||||
PROP_FD,
|
|
||||||
PROP_SPEW_CONTROL,
|
|
||||||
- PROP_RTS_CTS,
|
|
||||||
PROP_FLASH_OK,
|
|
||||||
|
|
||||||
LAST_PROP
|
|
||||||
@@ -97,7 +96,6 @@ struct _MMPortSerialPrivate {
|
|
||||||
guint stopbits;
|
|
||||||
guint64 send_delay;
|
|
||||||
gboolean spew_control;
|
|
||||||
- gboolean rts_cts;
|
|
||||||
gboolean flash_ok;
|
|
||||||
|
|
||||||
guint queue_id;
|
|
||||||
@@ -433,21 +431,19 @@ real_config_fd (MMPortSerial *self, int fd, GError **error)
|
|
||||||
errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
- stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY );
|
|
||||||
+ stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARENB | PARODD | CRTSCTS);
|
|
||||||
+ stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXOFF | IXANY );
|
|
||||||
stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET);
|
|
||||||
stbuf.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL);
|
|
||||||
stbuf.c_cc[VMIN] = 1;
|
|
||||||
stbuf.c_cc[VTIME] = 0;
|
|
||||||
stbuf.c_cc[VEOF] = 1;
|
|
||||||
|
|
||||||
- /* Use software handshaking and ignore parity/framing errors */
|
|
||||||
- stbuf.c_iflag |= (IXON | IXOFF | IXANY | IGNPAR);
|
|
||||||
+ /* Ignore parity/framing errors */
|
|
||||||
+ stbuf.c_iflag |= IGNPAR;
|
|
||||||
|
|
||||||
- /* Set up port speed and serial attributes; also ignore modem control
|
|
||||||
- * lines since most drivers don't implement RTS/CTS anyway.
|
|
||||||
- */
|
|
||||||
- stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARENB | CRTSCTS);
|
|
||||||
- stbuf.c_cflag |= (bits | CREAD | 0 | parity | stopbits | CLOCAL);
|
|
||||||
+ /* Set up port speed and serial attributes and enable receiver in local mode */
|
|
||||||
+ stbuf.c_cflag |= (bits | parity | stopbits | CLOCAL | CREAD);
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
if (cfsetispeed (&stbuf, speed) != 0) {
|
|
||||||
@@ -1621,10 +1617,6 @@ set_speed (MMPortSerial *self, speed_t speed, GError **error)
|
|
||||||
cfsetospeed (&options, speed);
|
|
||||||
options.c_cflag |= (CLOCAL | CREAD);
|
|
||||||
|
|
||||||
- /* Configure flow control as well here */
|
|
||||||
- if (self->priv->rts_cts)
|
|
||||||
- options.c_cflag |= (CRTSCTS);
|
|
||||||
-
|
|
||||||
return internal_tcsetattr (self, self->priv->fd, &options, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1928,9 +1920,6 @@ set_property (GObject *object,
|
|
||||||
case PROP_SPEW_CONTROL:
|
|
||||||
self->priv->spew_control = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
- case PROP_RTS_CTS:
|
|
||||||
- self->priv->rts_cts = g_value_get_boolean (value);
|
|
||||||
- break;
|
|
||||||
case PROP_FLASH_OK:
|
|
||||||
self->priv->flash_ok = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
@@ -1970,9 +1959,6 @@ get_property (GObject *object,
|
|
||||||
case PROP_SPEW_CONTROL:
|
|
||||||
g_value_set_boolean (value, self->priv->spew_control);
|
|
||||||
break;
|
|
||||||
- case PROP_RTS_CTS:
|
|
||||||
- g_value_set_boolean (value, self->priv->rts_cts);
|
|
||||||
- break;
|
|
||||||
case PROP_FLASH_OK:
|
|
||||||
g_value_set_boolean (value, self->priv->flash_ok);
|
|
||||||
break;
|
|
||||||
@@ -2081,14 +2067,6 @@ mm_port_serial_class_init (MMPortSerialClass *klass)
|
|
||||||
G_PARAM_READWRITE));
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
- (object_class, PROP_RTS_CTS,
|
|
||||||
- g_param_spec_boolean (MM_PORT_SERIAL_RTS_CTS,
|
|
||||||
- "RTSCTS",
|
|
||||||
- "Enable RTS/CTS flow control",
|
|
||||||
- FALSE,
|
|
||||||
- G_PARAM_READWRITE));
|
|
||||||
-
|
|
||||||
- g_object_class_install_property
|
|
||||||
(object_class, PROP_FLASH_OK,
|
|
||||||
g_param_spec_boolean (MM_PORT_SERIAL_FLASH_OK,
|
|
||||||
"FlashOk",
|
|
||||||
diff --git a/src/mm-port-serial.h b/src/mm-port-serial.h
|
|
||||||
index 223b9ce1c4a4..0514e3607101 100644
|
|
||||||
--- a/src/mm-port-serial.h
|
|
||||||
+++ b/src/mm-port-serial.h
|
|
||||||
@@ -36,7 +36,6 @@
|
|
||||||
#define MM_PORT_SERIAL_PARITY "parity"
|
|
||||||
#define MM_PORT_SERIAL_STOPBITS "stopbits"
|
|
||||||
#define MM_PORT_SERIAL_SEND_DELAY "send-delay"
|
|
||||||
-#define MM_PORT_SERIAL_RTS_CTS "rts-cts"
|
|
||||||
#define MM_PORT_SERIAL_FD "fd" /* Construct-only */
|
|
||||||
#define MM_PORT_SERIAL_SPEW_CONTROL "spew-control" /* Construct-only */
|
|
||||||
#define MM_PORT_SERIAL_FLASH_OK "flash-ok" /* Construct-only */
|
|
||||||
|
|
@ -1,211 +0,0 @@
|
||||||
From: Aleksander Morgado <aleksander@aleksander.es>
|
|
||||||
Date: Sat, 25 Mar 2017 18:30:02 +0100
|
|
||||||
Subject: [PATCH] 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
|
|
||||||
---
|
|
||||||
src/mm-broadband-bearer.c | 32 ++++++++++++++++++++++++++++++++
|
|
||||||
src/mm-broadband-modem.c | 36 +++++++++++++++++++++++++-----------
|
|
||||||
src/mm-broadband-modem.h | 4 ++++
|
|
||||||
3 files changed, 61 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/mm-broadband-bearer.c b/src/mm-broadband-bearer.c
|
|
||||||
index 0565eee3afeb..facbc1457603 100644
|
|
||||||
--- a/src/mm-broadband-bearer.c
|
|
||||||
+++ b/src/mm-broadband-bearer.c
|
|
||||||
@@ -259,6 +259,14 @@ dial_cdma_ready (MMBaseModem *modem,
|
|
||||||
* connect_succeeded(), we do it right away so that we stop our polling. */
|
|
||||||
mm_port_set_connected (ctx->data, TRUE);
|
|
||||||
|
|
||||||
+ /* Configure flow control to use while connected */
|
|
||||||
+ if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (ctx->data),
|
|
||||||
+ mm_broadband_modem_get_connected_flow_control (MM_BROADBAND_MODEM (modem)),
|
|
||||||
+ &error)) {
|
|
||||||
+ mm_warn ("Couldn't set flow control settings: %s", error->message);
|
|
||||||
+ g_clear_error (&error);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Keep port open during connection */
|
|
||||||
ctx->close_data_on_exit = FALSE;
|
|
||||||
|
|
||||||
@@ -557,6 +565,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 +586,14 @@ atd_ready (MMBaseModem *modem,
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Configure flow control to use while connected */
|
|
||||||
+ if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (ctx->dial_port),
|
|
||||||
+ mm_broadband_modem_get_connected_flow_control (MM_BROADBAND_MODEM (modem)),
|
|
||||||
+ &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. */
|
|
||||||
@@ -1452,9 +1470,16 @@ data_flash_cdma_ready (MMPortSerial *data,
|
|
||||||
DetailedDisconnectContext *ctx)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
+ GError *flow_control_error = NULL;
|
|
||||||
|
|
||||||
mm_port_serial_flash_finish (data, res, &error);
|
|
||||||
|
|
||||||
+ /* Cleanup flow control */
|
|
||||||
+ 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);
|
|
||||||
@@ -1569,9 +1594,16 @@ data_flash_3gpp_ready (MMPortSerial *data,
|
|
||||||
DetailedDisconnectContext *ctx)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
+ GError *flow_control_error = NULL;
|
|
||||||
|
|
||||||
mm_port_serial_flash_finish (data, res, &error);
|
|
||||||
|
|
||||||
+ /* Cleanup flow control */
|
|
||||||
+ 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);
|
|
||||||
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
|
|
||||||
index e5ad354882bb..3aa6e5f37424 100644
|
|
||||||
--- a/src/mm-broadband-modem.c
|
|
||||||
+++ b/src/mm-broadband-modem.c
|
|
||||||
@@ -146,6 +146,7 @@ struct _MMBroadbandModemPrivate {
|
|
||||||
guint modem_cind_max_signal_quality;
|
|
||||||
guint modem_cind_indicator_roaming;
|
|
||||||
guint modem_cind_indicator_service;
|
|
||||||
+ MMFlowControl modem_flow_control;
|
|
||||||
|
|
||||||
/*<--- Modem 3GPP interface --->*/
|
|
||||||
/* Properties */
|
|
||||||
@@ -3101,17 +3102,20 @@ modem_setup_flow_control_finish (MMIfaceModem *self,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
-ifc_test_ready (MMBaseModem *self,
|
|
||||||
+ifc_test_ready (MMBaseModem *_self,
|
|
||||||
GAsyncResult *res,
|
|
||||||
GTask *task)
|
|
||||||
{
|
|
||||||
- GError *error = NULL;
|
|
||||||
- const gchar *response;
|
|
||||||
- MMFlowControl mask;
|
|
||||||
- const gchar *cmd;
|
|
||||||
+ MMBroadbandModem *self;
|
|
||||||
+ GError *error = NULL;
|
|
||||||
+ const gchar *response;
|
|
||||||
+ MMFlowControl mask;
|
|
||||||
+ const gchar *cmd;
|
|
||||||
+
|
|
||||||
+ self = MM_BROADBAND_MODEM (_self);
|
|
||||||
|
|
||||||
/* Completely ignore errors in AT+IFC=? */
|
|
||||||
- response = mm_base_modem_at_command_finish (self, res, &error);
|
|
||||||
+ response = mm_base_modem_at_command_finish (_self, res, &error);
|
|
||||||
if (!response)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
@@ -3125,17 +3129,20 @@ ifc_test_ready (MMBaseModem *self,
|
|
||||||
* XON/XOFF
|
|
||||||
* None.
|
|
||||||
*/
|
|
||||||
- if (mask & MM_FLOW_CONTROL_RTS_CTS)
|
|
||||||
+ if (mask & MM_FLOW_CONTROL_RTS_CTS) {
|
|
||||||
+ self->priv->modem_flow_control = MM_FLOW_CONTROL_RTS_CTS;
|
|
||||||
cmd = "+IFC=2,2";
|
|
||||||
- else if (mask & MM_FLOW_CONTROL_XON_XOFF)
|
|
||||||
+ } else if (mask & MM_FLOW_CONTROL_XON_XOFF) {
|
|
||||||
+ self->priv->modem_flow_control = MM_FLOW_CONTROL_XON_XOFF;
|
|
||||||
cmd = "+IFC=1,1";
|
|
||||||
- else if (mask & MM_FLOW_CONTROL_NONE)
|
|
||||||
+ } else if (mask & MM_FLOW_CONTROL_NONE) {
|
|
||||||
+ self->priv->modem_flow_control = MM_FLOW_CONTROL_NONE;
|
|
||||||
cmd = "+IFC=0,0";
|
|
||||||
- else
|
|
||||||
+ } else
|
|
||||||
g_assert_not_reached ();
|
|
||||||
|
|
||||||
/* Set flow control settings and ignore result */
|
|
||||||
- mm_base_modem_at_command (self, cmd, 3, FALSE, NULL, NULL);
|
|
||||||
+ mm_base_modem_at_command (_self, cmd, 3, FALSE, NULL, NULL);
|
|
||||||
|
|
||||||
out:
|
|
||||||
/* Ignore errors */
|
|
||||||
@@ -10332,6 +10339,12 @@ mm_broadband_modem_get_current_charset (MMBroadbandModem *self)
|
|
||||||
return self->priv->modem_current_charset;
|
|
||||||
}
|
|
||||||
|
|
||||||
+MMFlowControl
|
|
||||||
+mm_broadband_modem_get_connected_flow_control (MMBroadbandModem *self)
|
|
||||||
+{
|
|
||||||
+ return self->priv->modem_flow_control;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
gchar *
|
|
||||||
mm_broadband_modem_create_device_identifier (MMBroadbandModem *self,
|
|
||||||
const gchar *ati,
|
|
||||||
@@ -10652,6 +10665,7 @@ mm_broadband_modem_init (MMBroadbandModem *self)
|
|
||||||
self->priv->current_sms_mem1_storage = MM_SMS_STORAGE_UNKNOWN;
|
|
||||||
self->priv->current_sms_mem2_storage = MM_SMS_STORAGE_UNKNOWN;
|
|
||||||
self->priv->sim_hot_swap_supported = FALSE;
|
|
||||||
+ self->priv->modem_flow_control = MM_FLOW_CONTROL_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
diff --git a/src/mm-broadband-modem.h b/src/mm-broadband-modem.h
|
|
||||||
index d6b55d9dd030..9ac4eabded65 100644
|
|
||||||
--- a/src/mm-broadband-modem.h
|
|
||||||
+++ b/src/mm-broadband-modem.h
|
|
||||||
@@ -24,6 +24,7 @@
|
|
||||||
|
|
||||||
#include <ModemManager.h>
|
|
||||||
|
|
||||||
+#include "mm-modem-helpers.h"
|
|
||||||
#include "mm-charsets.h"
|
|
||||||
#include "mm-base-modem.h"
|
|
||||||
|
|
||||||
@@ -109,6 +110,9 @@ gchar *mm_broadband_modem_take_and_convert_to_current_charset (MMBroadbandModem
|
|
||||||
|
|
||||||
MMModemCharset mm_broadband_modem_get_current_charset (MMBroadbandModem *self);
|
|
||||||
|
|
||||||
+/* Get the flow control setting to apply when connected, if any */
|
|
||||||
+MMFlowControl mm_broadband_modem_get_connected_flow_control (MMBroadbandModem *self);
|
|
||||||
+
|
|
||||||
/* Create a unique device identifier string using the ATI and ATI1 replies and some
|
|
||||||
* additional internal info */
|
|
||||||
gchar *mm_broadband_modem_create_device_identifier (MMBroadbandModem *self,
|
|
||||||
|
|
@ -15,16 +15,8 @@ PV = "1.7.0+git${SRCPV}"
|
||||||
SRC_URI = " \
|
SRC_URI = " \
|
||||||
git://anongit.freedesktop.org/git/ModemManager/ModemManager.git;protocol=https \
|
git://anongit.freedesktop.org/git/ModemManager/ModemManager.git;protocol=https \
|
||||||
file://0001-configure.ac-add-foreign-automake-option.patch \
|
file://0001-configure.ac-add-foreign-automake-option.patch \
|
||||||
file://0002-helpers-new-parser-for-AT-IFC.patch \
|
|
||||||
file://0003-broadband-modem-query-supported-flow-control-modes-b.patch \
|
|
||||||
file://0004-wavecom-ignore-custom-flow-control-handling.patch \
|
|
||||||
file://0005-telit-ignore-custom-flow-control-handling.patch \
|
|
||||||
file://0006-port-serial-new-internal-method-to-run-tcsetattr.patch \
|
|
||||||
file://0007-port-serial-new-method-to-explicitly-set-flow-contro.patch \
|
|
||||||
file://0008-port-serial-remove-all-default-flow-control-settings.patch \
|
|
||||||
file://0009-broadband-bearer-once-connected-set-flow-control-set.patch \
|
|
||||||
"
|
"
|
||||||
SRCREV = "34443289d97da5c95270c6071d140f4567047624"
|
SRCREV = "d09bc8baaa9fe93a72bb715530b1403a7a81c891"
|
||||||
|
|
||||||
S = "${WORKDIR}/git"
|
S = "${WORKDIR}/git"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue