Try to normalize both operator name and code

2017-03-25 Thread Aleksander Morgado
Hey Colin and Dan,

What do you think of these two patches?

Cheers!

[PATCH 1/2] modem-helpers: if operator not in UCS2, see if already
[PATCH 2/2] broadband-modem: normalize also operator code
___
ModemManager-devel mailing list
ModemManager-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel


[PATCH 2/2] broadband-modem: normalize also operator code

2017-03-25 Thread Aleksander Morgado
The operator code (MCCMNC) may also be given encoded in the current
charset (e.g. UCS2).

Based on a patch from Colin Helliwell 
---
 plugins/altair/mm-broadband-modem-altair-lte.c | 2 +-
 src/mm-broadband-modem.c   | 6 --
 src/mm-modem-helpers.c | 4 ++--
 src/mm-modem-helpers.h | 4 ++--
 src/tests/test-modem-helpers.c | 7 ++-
 5 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/plugins/altair/mm-broadband-modem-altair-lte.c 
b/plugins/altair/mm-broadband-modem-altair-lte.c
index 1155a7a1..3cbc7ecb 100644
--- a/plugins/altair/mm-broadband-modem-altair-lte.c
+++ b/plugins/altair/mm-broadband-modem-altair-lte.c
@@ -1128,7 +1128,7 @@ modem_3gpp_load_operator_name_finish (MMIfaceModem3gpp 
*self,
error))
 return NULL;
 
-mm_3gpp_normalize_operator_name (_name, MM_MODEM_CHARSET_UNKNOWN);
+mm_3gpp_normalize_operator (_name, MM_MODEM_CHARSET_UNKNOWN);
 if (operator_name)
 mm_dbg ("loaded Operator Name: %s", operator_name);
 return operator_name;
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 302fc3db..e98f8dc0 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -3472,7 +3472,9 @@ modem_3gpp_load_operator_code_finish (MMIfaceModem3gpp 
*self,
error))
 return NULL;
 
-mm_dbg ("loaded Operator Code: %s", operator_code);
+mm_3gpp_normalize_operator (_code, MM_BROADBAND_MODEM 
(self)->priv->modem_current_charset);
+if (operator_code)
+mm_dbg ("loaded Operator Code: %s", operator_code);
 return operator_code;
 }
 
@@ -3513,7 +3515,7 @@ modem_3gpp_load_operator_name_finish (MMIfaceModem3gpp 
*self,
error))
 return NULL;
 
-mm_3gpp_normalize_operator_name (_name, MM_BROADBAND_MODEM 
(self)->priv->modem_current_charset);
+mm_3gpp_normalize_operator (_name, MM_BROADBAND_MODEM 
(self)->priv->modem_current_charset);
 if (operator_name)
 mm_dbg ("loaded Operator Name: %s", operator_name);
 return operator_name;
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 9266a5a0..b4556176 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -3123,8 +3123,8 @@ mm_string_to_access_tech (const gchar *string)
 /*/
 
 void
-mm_3gpp_normalize_operator_name (gchar  **operator,
- MMModemCharset   cur_charset)
+mm_3gpp_normalize_operator (gchar  **operator,
+MMModemCharset   cur_charset)
 {
 g_assert (operator);
 
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 33af48b6..a74924e3 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -294,8 +294,8 @@ gchar *mm_3gpp_facility_to_acronym (MMModem3gppFacility 
facility);
 
 MMModemAccessTechnology mm_string_to_access_tech (const gchar *string);
 
-void mm_3gpp_normalize_operator_name (gchar  **operator,
-  MMModemCharset   cur_charset);
+void mm_3gpp_normalize_operator (gchar  **operator,
+ MMModemCharset   cur_charset);
 
 gboolean mm_3gpp_parse_operator_id (const gchar *operator_id,
 guint16 *mcc,
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index 98f30f83..ae0eec99 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -876,13 +876,18 @@ typedef struct {
 static const NormalizeOperatorTest normalize_operator_tests[] = {
 /* charset unknown */
 { "Verizon", MM_MODEM_CHARSET_UNKNOWN, "Verizon" },
+{ "311480",  MM_MODEM_CHARSET_UNKNOWN, "311480"  },
 /* charset configured as IRA (ASCII) */
 { "Verizon", MM_MODEM_CHARSET_IRA, "Verizon" },
+{ "311480",  MM_MODEM_CHARSET_IRA, "311480"  },
 /* charset configured as GSM7 */
 { "Verizon", MM_MODEM_CHARSET_GSM, "Verizon" },
+{ "311480",  MM_MODEM_CHARSET_GSM, "311480"  },
 /* charset configured as UCS2 */
 { "0056006500720069007A006F006E", MM_MODEM_CHARSET_UCS2, "Verizon" },
+{ "003300310031003400380030", MM_MODEM_CHARSET_UCS2, "311480"  },
 { "Verizon",  MM_MODEM_CHARSET_UCS2, "Verizon" },
+{ "311480",   MM_MODEM_CHARSET_UCS2, "311480"  },
 };
 
 static void
@@ -891,7 +896,7 @@ common_test_normalize_operator (const NormalizeOperatorTest 
*t)
 gchar *str;
 
 str = g_strdup (t->input);
-mm_3gpp_normalize_operator_name (, t->charset);
+mm_3gpp_normalize_operator (, t->charset);
 if (!t->normalized)
 g_assert (!str);
 else
-- 
2.12.0

___
ModemManager-devel mailing list

[PATCH 1/2] modem-helpers: if operator not in UCS2, see if already valid UTF-8

2017-03-25 Thread Aleksander Morgado
The method doing the operator name normalization takes as input the
current configured modem charset. If this is UCS2, we will now just
assume this is a hint: the string may or may not come in hex/UCS2.

This logic makes the custom operator name loading in Huawei unneeded,
if the modem is configured in UCS2, we still properly process operator
names coming in plain ASCII.
---
 plugins/huawei/mm-broadband-modem-huawei.c | 51 --
 src/mm-modem-helpers.c | 26 +--
 src/tests/test-modem-helpers.c | 45 ++
 3 files changed, 62 insertions(+), 60 deletions(-)

diff --git a/plugins/huawei/mm-broadband-modem-huawei.c 
b/plugins/huawei/mm-broadband-modem-huawei.c
index 74e680b4..9f13b0f2 100644
--- a/plugins/huawei/mm-broadband-modem-huawei.c
+++ b/plugins/huawei/mm-broadband-modem-huawei.c
@@ -2172,55 +2172,6 @@ modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp 
*self,
 }
 
 /*/
-/* Operator Name loading (3GPP interface) */
-
-static gchar *
-modem_3gpp_load_operator_name_finish (MMIfaceModem3gpp *self,
-  GAsyncResult *res,
-  GError **error)
-{
-const gchar *result;
-gchar *operator_name = NULL;
-
-result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, 
error);
-if (!result)
-return NULL;
-
-if (!mm_3gpp_parse_cops_read_response (result,
-   NULL, /* mode */
-   NULL, /* format */
-   _name,
-   NULL, /* act */
-   error))
-return NULL;
-
-/* Despite +CSCS? may claim supporting UCS2, Huawei modems always report 
the
- * operator name in ASCII in a +COPS response. Thus, we ignore the current
- * charset claimed by the modem and assume the charset is IRA when parsing
- * the operator name.
- */
-mm_3gpp_normalize_operator_name (_name, MM_MODEM_CHARSET_IRA);
-if (operator_name)
-mm_dbg ("loaded Operator Name: %s", operator_name);
-
-return operator_name;
-}
-
-static void
-modem_3gpp_load_operator_name (MMIfaceModem3gpp *self,
-   GAsyncReadyCallback callback,
-   gpointer user_data)
-{
-mm_dbg ("loading Operator Name (huawei)...");
-mm_base_modem_at_command (MM_BASE_MODEM (self),
-  "+COPS=3,0;+COPS?",
-  3,
-  FALSE,
-  callback,
-  user_data);
-}
-
-/*/
 /* Create Bearer (Modem interface) */
 
 typedef struct {
@@ -4603,8 +4554,6 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
 iface->enable_unsolicited_events_finish = 
modem_3gpp_enable_unsolicited_events_finish;
 iface->disable_unsolicited_events = modem_3gpp_disable_unsolicited_events;
 iface->disable_unsolicited_events_finish = 
modem_3gpp_disable_unsolicited_events_finish;
-iface->load_operator_name = modem_3gpp_load_operator_name;
-iface->load_operator_name_finish = modem_3gpp_load_operator_name_finish;
 }
 
 static void
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index fc95e28f..9266a5a0 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -3131,20 +3131,28 @@ mm_3gpp_normalize_operator_name (gchar  
**operator,
 if (*operator == NULL)
 return;
 
-/* Some modems (Option & HSO) return the operator name as a hexadecimal
- * string of the bytes of the operator name as encoded by the current
- * character set.
- */
+/* Despite +CSCS? may claim supporting UCS2, Some modems (e.g. Huawei)
+ * always report the operator name in ASCII in a +COPS response. */
 if (cur_charset == MM_MODEM_CHARSET_UCS2) {
+gchar *tmp;
+
+tmp = g_strdup (*operator);
 /* In this case we're already checking UTF-8 validity */
-*operator = mm_charset_take_and_convert_to_utf8 (*operator, 
MM_MODEM_CHARSET_UCS2);
+tmp = mm_charset_take_and_convert_to_utf8 (tmp, cur_charset);
+if (tmp) {
+g_clear_pointer (operator, g_free);
+*operator = tmp;
+goto out;
+}
 }
-/* Ensure the operator name is valid UTF-8 so that we can send it
- * through D-Bus and such.
- */
-else if (!g_utf8_validate (*operator, -1, NULL))
+
+/* Charset is unknown or there was an error in conversion; try to see
+ * if the contents we got are valid UTF-8 already. */
+if (!g_utf8_validate (*operator, -1, NULL))
 g_clear_pointer (operator, g_free);
 
+out:
+
 /* Some modems (Novatel LTE) return 

[PATCH 7/8] port-serial: remove all default flow control settings

2017-03-25 Thread Aleksander Morgado
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 e55f9062..04ab17fe 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 (, speed) != 0) {
@@ -1621,10 +1617,6 @@ set_speed (MMPortSerial *self, speed_t speed, GError 
**error)
 cfsetospeed (, 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, , 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 223b9ce1..0514e360 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 */
-- 
2.12.0

___
ModemManager-devel mailing list
ModemManager-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel


[PATCH 4/8] telit: ignore custom flow control handling

2017-03-25 Thread Aleksander Morgado
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 6ef340f1..d63cb0aa 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)) & 0x) {
-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;
-- 
2.12.0

___
ModemManager-devel mailing list
ModemManager-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel


[PATCH 8/8] broadband-bearer: once connected, set flow control settings

2017-03-25 Thread Aleksander Morgado
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 9491f5a8..bccee72b 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)),
+  )) {
+mm_warn ("Couldn't set flow control settings: %s", error->message);
+g_clear_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)),
+  )) {
+mm_warn ("Couldn't set flow control settings: %s", error->message);
+g_clear_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, );
 
+/* Cleanup flow control */
+if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (data), 
MM_FLOW_CONTROL_NONE, _control_error)) {
+mm_dbg ("Couldn't reset flow control settings: %s", 
flow_control_error->message);
+g_clear_error (_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, );
 
+/* Cleanup flow control */
+if (!mm_port_serial_set_flow_control (MM_PORT_SERIAL (data), 
MM_FLOW_CONTROL_NONE, _control_error)) {
+mm_dbg ("Couldn't reset flow control settings: %s", 
flow_control_error->message);
+g_clear_error (_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 e7376310..83302f63 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  

[PATCH 6/8] port-serial: new method to explicitly set flow control settings

2017-03-25 Thread Aleksander Morgado
---
 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 f2b97a02..e55f9062 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 (, 0, sizeof (struct termios));
+if (tcgetattr (self->priv->fd, ) != 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, , 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 708e3912..223b9ce1 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 */
-- 
2.12.0

___
ModemManager-devel mailing list
ModemManager-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel


[PATCH 2/8] broadband-modem: query supported flow control modes before setting

2017-03-25 Thread Aleksander Morgado
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 302fc3db..e7376310 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, );
+if (!response)
+goto out;
+
+/* Parse response */
+mask = mm_parse_ifc_test_response (response, );
+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);
 }
 
 /*/
-- 
2.12.0

___
ModemManager-devel mailing list
ModemManager-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel


[PATCH 3/8] wavecom: ignore custom flow control handling

2017-03-25 Thread Aleksander Morgado
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 47c6b4f0..0e93e47e 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;
-- 
2.12.0

___
ModemManager-devel mailing list
ModemManager-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel