diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0002-helpers-new-parser-for-AT-IFC.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0002-helpers-new-parser-for-AT-IFC.patch new file mode 100644 index 000000000..d213da5db --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0002-helpers-new-parser-for-AT-IFC.patch @@ -0,0 +1,290 @@ +From: Aleksander Morgado +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: (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)); diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0003-broadband-modem-query-supported-flow-control-modes-b.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0003-broadband-modem-query-supported-flow-control-modes-b.patch new file mode 100644 index 000000000..9250ab595 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0003-broadband-modem-query-supported-flow-control-modes-b.patch @@ -0,0 +1,113 @@ +From: Aleksander Morgado +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); + } + + /*****************************************************************************/ diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0004-wavecom-ignore-custom-flow-control-handling.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0004-wavecom-ignore-custom-flow-control-handling.patch new file mode 100644 index 000000000..732de7716 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0004-wavecom-ignore-custom-flow-control-handling.patch @@ -0,0 +1,55 @@ +From: Aleksander Morgado +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; diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0005-telit-ignore-custom-flow-control-handling.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0005-telit-ignore-custom-flow-control-handling.patch new file mode 100644 index 000000000..deb6ccca4 --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0005-telit-ignore-custom-flow-control-handling.patch @@ -0,0 +1,76 @@ +From: Aleksander Morgado +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; diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0006-port-serial-new-internal-method-to-run-tcsetattr.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0006-port-serial-new-internal-method-to-run-tcsetattr.patch new file mode 100644 index 000000000..c3fa9c7ad --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0006-port-serial-new-internal-method-to-run-tcsetattr.patch @@ -0,0 +1,167 @@ +From: Aleksander Morgado +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); + } + + /*****************************************************************************/ diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0007-port-serial-new-method-to-explicitly-set-flow-contro.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0007-port-serial-new-method-to-explicitly-set-flow-contro.patch new file mode 100644 index 000000000..b7226319c --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0007-port-serial-new-method-to-explicitly-set-flow-contro.patch @@ -0,0 +1,92 @@ +From: Aleksander Morgado +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 + #include + ++#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 */ diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0008-port-serial-remove-all-default-flow-control-settings.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0008-port-serial-remove-all-default-flow-control-settings.patch new file mode 100644 index 000000000..81afd5d9a --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0008-port-serial-remove-all-default-flow-control-settings.patch @@ -0,0 +1,118 @@ +From: Aleksander Morgado +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 */ diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0009-broadband-bearer-once-connected-set-flow-control-set.patch b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0009-broadband-bearer-once-connected-set-flow-control-set.patch new file mode 100644 index 000000000..2beaaea4d --- /dev/null +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager/0009-broadband-bearer-once-connected-set-flow-control-set.patch @@ -0,0 +1,211 @@ +From: Aleksander Morgado +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 + ++#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, diff --git a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_git.bb b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_git.bb index 0ed4553a1..53d576446 100644 --- a/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_git.bb +++ b/meta-digi-dey/recipes-connectivity/modemmanager/modemmanager_git.bb @@ -15,6 +15,14 @@ PV = "1.7.0+git${SRCPV}" SRC_URI = " \ git://anongit.freedesktop.org/git/ModemManager/ModemManager.git;protocol=https \ 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"