diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-08-21 10:23:42 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-08-29 17:26:46 +0200 |
commit | e9aff3ba42c3b29c529c155694c7df3770792814 (patch) | |
tree | 09c20ba9fe94eab308aab4971465e33381a4663d /src | |
parent | 7369f1675972e203b906315a9c79f851fbca6c7d (diff) |
base-modem: allow grabbing multiple 'net' and 'qmi' ports
All grabbed 'net' ports are added to the new list of data ports. It is a task
for the specific plugin to decide how each of the data ports should be
connected. In the case of not having 'net' ports, the list of data ports will
only contain a single AT port.
All grabbed 'qmi' ports are added to the new list of QMI ports. The first port
in the list is to be considered the 'primary' one, and will be the one used
for all services. The remaining QMI ports, if any, will only be used to for WDS,
to manage the associated 'net' ports.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-base-modem.c | 121 |
1 files changed, 79 insertions, 42 deletions
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c index d0102126..642201aa 100644 --- a/src/mm-base-modem.c +++ b/src/mm-base-modem.c @@ -77,15 +77,15 @@ struct _MMBaseModemPrivate { MMAtSerialPort *primary; MMAtSerialPort *secondary; MMQcdmSerialPort *qcdm; - MMPort *data; + GList *data; /* GPS-enabled modems will have an AT port for control, and a raw serial * port to receive all GPS traces */ MMAtSerialPort *gps_control; MMGpsSerialPort *gps; - /* QMI port */ - MMQmiPort *qmi; + /* QMI ports */ + GList *qmi; }; static gchar * @@ -162,7 +162,7 @@ mm_base_modem_grab_port (MMBaseModem *self, g_return_val_if_fail (subsys != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); - /* Only allow 'tty' and 'net' ports */ + /* Only allow 'tty', 'net' and 'cdc-wdm' ports */ if (!g_str_equal (subsys, "net") && !g_str_equal (subsys, "tty") && !(g_str_equal (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm"))) { @@ -260,6 +260,7 @@ mm_base_modem_release_port (MMBaseModem *self, { gchar *key; MMPort *port; + GList *l; g_return_if_fail (MM_IS_BASE_MODEM (self)); g_return_if_fail (name != NULL); @@ -288,8 +289,11 @@ mm_base_modem_release_port (MMBaseModem *self, g_clear_object (&self->priv->primary); } - if (port == (MMPort *)self->priv->data) - g_clear_object (&self->priv->data); + l = g_list_find (self->priv->data, port); + if (l) { + g_object_unref (l->data); + self->priv->data = g_list_delete_link (self->priv->data, l); + } if (port == (MMPort *)self->priv->secondary) g_clear_object (&self->priv->secondary); @@ -303,8 +307,11 @@ mm_base_modem_release_port (MMBaseModem *self, if (port == (MMPort *)self->priv->gps) g_clear_object (&self->priv->gps); - if (port == (MMPort *)self->priv->qmi) - g_clear_object (&self->priv->qmi); + l = g_list_find (self->priv->qmi, port); + if (l) { + g_object_unref (l->data); + self->priv->qmi = g_list_delete_link (self->priv->qmi, l); + } /* Remove it from the tracking HT */ mm_dbg ("(%s/%s) type %s released from %s", @@ -509,7 +516,8 @@ mm_base_modem_get_port_qmi (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); - return (self->priv->qmi ? g_object_ref (self->priv->qmi) : NULL); + /* First QMI port in the list is the primary one always */ + return (self->priv->qmi ? ((MMQmiPort *)g_object_ref (self->priv->qmi->data)) : NULL); } MMQmiPort * @@ -517,7 +525,8 @@ mm_base_modem_peek_port_qmi (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); - return self->priv->qmi; + /* First QMI port in the list is the primary one always */ + return (self->priv->qmi ? (MMQmiPort *)self->priv->qmi->data : NULL); } MMPort * @@ -532,14 +541,17 @@ mm_base_modem_get_best_data_port (MMBaseModem *self) MMPort * mm_base_modem_peek_best_data_port (MMBaseModem *self) { + GList *l; + g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); - /* TODO: sometime we'll have a list of available data ports to use instead - * of a single one */ + /* Return first not-connected data port */ + for (l = self->priv->data; l; l = g_list_next (l)) { + if (!mm_port_get_connected ((MMPort *)l->data)) + return (MMPort *)l->data; + } - return (mm_port_get_connected (self->priv->data) ? - NULL : - self->priv->data); + return NULL; } MMAtSerialPort * @@ -641,8 +653,11 @@ mm_base_modem_organize_ports (MMBaseModem *self, MMQcdmSerialPort *qcdm = NULL; MMAtSerialPort *gps_control = NULL; MMGpsSerialPort *gps = NULL; - MMPort *data = NULL; - MMPort *qmi = NULL; + MMPort *data_primary = NULL; + GList *data = NULL; + MMPort *qmi_primary = NULL; + GList *qmi = NULL; + GList *l; g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE); @@ -670,8 +685,8 @@ mm_base_modem_organize_ports (MMBaseModem *self, } } - if (!data && (flags & MM_AT_PORT_FLAG_PPP)) - data = candidate; + if (!data_primary && (flags & MM_AT_PORT_FLAG_PPP)) + data_primary = candidate; /* Explicitly flagged secondary ports trump NONE ports for secondary */ if (flags & MM_AT_PORT_FLAG_SECONDARY) { @@ -701,8 +716,11 @@ mm_base_modem_organize_ports (MMBaseModem *self, case MM_PORT_TYPE_NET: /* Net device (if any) is the preferred data port */ - if (!data || MM_IS_AT_SERIAL_PORT (data)) - data = candidate; + if (!data_primary || MM_IS_AT_SERIAL_PORT (data_primary)) + data_primary = candidate; + else + /* All non-primary net ports get added to the list of data ports */ + data = g_list_append (data, candidate); break; case MM_PORT_TYPE_GPS: @@ -712,8 +730,11 @@ mm_base_modem_organize_ports (MMBaseModem *self, break; case MM_PORT_TYPE_QMI: - if (!qmi) - qmi = candidate; + if (!qmi_primary) + qmi_primary = candidate; + else + /* All non-primary QMI ports get added to the list of QMI ports */ + qmi = g_list_append (qmi, candidate); break; default: @@ -743,41 +764,55 @@ mm_base_modem_organize_ports (MMBaseModem *self, secondary = backup_primary ? backup_primary : backup_secondary; /* Data port defaults to primary AT port */ - if (!data) - data = MM_PORT (primary); - g_assert (data); + if (!data_primary) + data_primary = MM_PORT (primary); + g_assert (data_primary); /* Reset flags on all ports; clear data port first since it might also * be the primary or secondary port. */ - if (MM_IS_AT_SERIAL_PORT (data)) - mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data), MM_AT_PORT_FLAG_NONE); + if (MM_IS_AT_SERIAL_PORT (data_primary)) + mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data_primary), MM_AT_PORT_FLAG_NONE); mm_at_serial_port_set_flags (primary, MM_AT_PORT_FLAG_PRIMARY); if (secondary) mm_at_serial_port_set_flags (secondary, MM_AT_PORT_FLAG_SECONDARY); - if (MM_IS_AT_SERIAL_PORT (data)) { - flags = mm_at_serial_port_get_flags (MM_AT_SERIAL_PORT (data)); - mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data), flags | MM_AT_PORT_FLAG_PPP); + if (MM_IS_AT_SERIAL_PORT (data_primary)) { + flags = mm_at_serial_port_get_flags (MM_AT_SERIAL_PORT (data_primary)); + mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data_primary), flags | MM_AT_PORT_FLAG_PPP); } - log_port (self, MM_PORT (primary), "primary"); - log_port (self, MM_PORT (secondary), "secondary"); - log_port (self, MM_PORT (data), "data"); - log_port (self, MM_PORT (qcdm), "qcdm"); - log_port (self, MM_PORT (gps_control), "gps control"); - log_port (self, MM_PORT (gps), "gps"); - log_port (self, MM_PORT (qmi), "qmi"); + log_port (self, MM_PORT (primary), "at (primary)"); + log_port (self, MM_PORT (secondary), "at (secondary)"); + log_port (self, MM_PORT (data_primary), "data (primary)"); + for (l = data; l; l = g_list_next (l)) + log_port (self, MM_PORT (l->data), "data (secondary)"); + log_port (self, MM_PORT (qcdm), "qcdm"); + log_port (self, MM_PORT (gps_control), "gps (control)"); + log_port (self, MM_PORT (gps), "gps (nmea)"); + log_port (self, MM_PORT (qmi_primary), "qmi (primary)"); + for (l = qmi; l; l = g_list_next (l)) + log_port (self, MM_PORT (l->data), "qmi (secondary)"); /* We keep new refs to the objects here */ self->priv->primary = g_object_ref (primary); self->priv->secondary = (secondary ? g_object_ref (secondary) : NULL); - self->priv->data = g_object_ref (data); self->priv->qcdm = (qcdm ? g_object_ref (qcdm) : NULL); self->priv->gps_control = (gps_control ? g_object_ref (gps_control) : NULL); self->priv->gps = (gps ? g_object_ref (gps) : NULL); - self->priv->qmi = (qmi ? g_object_ref (qmi) : NULL); + + /* Build the final list of data ports, primary port first */ + self->priv->data = g_list_append (self->priv->data, g_object_ref (data_primary)); + g_list_foreach (data, (GFunc)g_object_ref, NULL); + self->priv->data = g_list_concat (self->priv->data, data); + + /* Build the final list of QMI ports, primary port first */ + if (qmi_primary) { + self->priv->qmi = g_list_append (self->priv->qmi, g_object_ref (qmi_primary)); + g_list_foreach (qmi, (GFunc)g_object_ref, NULL); + self->priv->qmi = g_list_concat (self->priv->qmi, qmi); + } /* As soon as we get the ports organized, we initialize the modem */ mm_base_modem_initialize (self, @@ -1048,11 +1083,13 @@ dispose (GObject *object) g_clear_object (&self->priv->primary); g_clear_object (&self->priv->secondary); - g_clear_object (&self->priv->data); + g_list_free_full (self->priv->data, g_object_unref); + self->priv->data = NULL; g_clear_object (&self->priv->qcdm); g_clear_object (&self->priv->gps_control); g_clear_object (&self->priv->gps); - g_clear_object (&self->priv->qmi); + g_list_free_full (self->priv->qmi, g_object_unref); + self->priv->qmi = NULL; if (self->priv->ports) { g_hash_table_destroy (self->priv->ports); |