[PATCH 1/2] base-modem: allow looking for the QMI port associated to a given data port
- From: Aleksander Morgado <aleksander lanedo com>
- To: Network Manager <networkmanager-list gnome org>
- Subject: [PATCH 1/2] base-modem: allow looking for the QMI port associated to a given data port
- Date: Thu, 30 Aug 2012 12:11:01 +0200
QMI and wwan ports come in pairs. Each wwan port has an associated control QMI
port, which is the only port allowed to send the Start|Stop Network QMI requests
to start|stop the connection in the given wwan interface.
Paired QMI and wwan interfaces (should) share the same parent udev device,
quoting Bjørn:
"If we ignore the unfortunate 3.4 and 3.5 kernels, then a matching wwanX
and cdc-wdmY set will always share the same parent USB interface on QMI
devices.
Having the same parent USB device is *not* sufficient. You cannot control
wwan0 using cdc-wdm1 in the above example."
---
src/mm-base-modem.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/mm-base-modem.h | 20 +++++----
2 files changed, 129 insertions(+), 9 deletions(-)
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index 6d2ea9c..af2e829 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <gudev/gudev.h>
#include <ModemManager.h>
#include <mm-errors-types.h>
@@ -529,6 +530,123 @@ mm_base_modem_peek_port_qmi (MMBaseModem *self)
return (self->priv->qmi ? (MMQmiPort *)self->priv->qmi->data : NULL);
}
+MMQmiPort *
+mm_base_modem_get_port_qmi_for_data (MMBaseModem *self,
+ MMPort *data,
+ GError **error)
+{
+ MMQmiPort *qmi;
+
+ qmi = mm_base_modem_peek_port_qmi_for_data (self, data, error);
+ return (qmi ? (MMQmiPort *)g_object_ref (qmi) : NULL);
+}
+
+MMQmiPort *
+mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self,
+ MMPort *data,
+ GError **error)
+{
+ MMQmiPort *found;
+ GUdevClient *client;
+ GUdevDevice *data_device;
+ GUdevDevice *data_device_parent;
+ GList *l;
+
+ if (mm_port_get_subsys (data) != MM_PORT_SUBSYS_NET) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot look for QMI port associated to a non-net data port");
+ return NULL;
+ }
+
+ /* don't listen for uevents */
+ client = g_udev_client_new (NULL);
+
+ /* Get udev device for the data port */
+ data_device = (g_udev_client_query_by_subsystem_and_name (
+ client,
+ "net",
+ mm_port_get_device (data)));
+ if (!data_device) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't find udev device for port 'net/%s'",
+ mm_port_get_device (data));
+ g_object_unref (client);
+ return NULL;
+ }
+
+ /* Get parent of the data device */
+ data_device_parent = g_udev_device_get_parent (data_device);
+ if (!data_device_parent) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't get udev device parent for port 'net/%s'",
+ mm_port_get_device (data));
+ g_object_unref (data_device);
+ g_object_unref (client);
+ return NULL;
+ }
+
+ /* Now walk the list of QMI ports looking for a match */
+ found = NULL;
+ for (l = self->priv->qmi; l && !found; l = g_list_next (l)) {
+ GUdevDevice *qmi_device;
+ GUdevDevice *qmi_device_parent;
+
+ /* Get udev device for the QMI port */
+ qmi_device = (g_udev_client_query_by_subsystem_and_name (
+ client,
+ "usb",
+ mm_port_get_device (MM_PORT (l->data))));
+ if (!qmi_device) {
+ qmi_device = (g_udev_client_query_by_subsystem_and_name (
+ client,
+ "usbmisc",
+ mm_port_get_device (MM_PORT (l->data))));
+ if (!qmi_device) {
+ mm_warn ("Couldn't get udev device for QMI port '%s'",
+ mm_port_get_device (MM_PORT (l->data)));
+ continue;
+ }
+ }
+
+ /* Get parent of the QMI device */
+ qmi_device_parent = g_udev_device_get_parent (qmi_device);
+ g_object_unref (qmi_device);
+
+ if (!data_device_parent) {
+ mm_warn ("Couldn't get udev device parent for QMI port '%s'",
+ mm_port_get_device (MM_PORT (l->data)));
+ continue;
+ }
+
+ if (g_str_equal (g_udev_device_get_sysfs_path (data_device_parent),
+ g_udev_device_get_sysfs_path (qmi_device_parent)))
+ found = MM_QMI_PORT (l->data);
+
+ g_object_unref (qmi_device_parent);
+ }
+
+ g_object_unref (data_device_parent);
+ g_object_unref (data_device);
+ g_object_unref (client);
+
+ if (!found) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_NOT_FOUND,
+ "Couldn't find associated QMI port for 'net/%s'",
+ mm_port_get_device (data));
+ return NULL;
+ }
+
+ return found;
+}
+
MMPort *
mm_base_modem_get_best_data_port (MMBaseModem *self)
{
diff --git a/src/mm-base-modem.h b/src/mm-base-modem.h
index 36a7a51..386fa8f 100644
--- a/src/mm-base-modem.h
+++ b/src/mm-base-modem.h
@@ -112,15 +112,16 @@ gboolean mm_base_modem_has_at_port (MMBaseModem *self);
gboolean mm_base_modem_organize_ports (MMBaseModem *self,
GError **error);
-MMAtSerialPort *mm_base_modem_peek_port_primary (MMBaseModem *self);
-MMAtSerialPort *mm_base_modem_peek_port_secondary (MMBaseModem *self);
-MMQcdmSerialPort *mm_base_modem_peek_port_qcdm (MMBaseModem *self);
-MMAtSerialPort *mm_base_modem_peek_port_gps_control (MMBaseModem *self);
-MMGpsSerialPort *mm_base_modem_peek_port_gps (MMBaseModem *self);
-MMQmiPort *mm_base_modem_peek_port_qmi (MMBaseModem *self);
-MMAtSerialPort *mm_base_modem_peek_best_at_port (MMBaseModem *self, GError **error);
-MMPort *mm_base_modem_peek_best_data_port (MMBaseModem *self);
-GList *mm_base_modem_peek_data_ports (MMBaseModem *self);
+MMAtSerialPort *mm_base_modem_peek_port_primary (MMBaseModem *self);
+MMAtSerialPort *mm_base_modem_peek_port_secondary (MMBaseModem *self);
+MMQcdmSerialPort *mm_base_modem_peek_port_qcdm (MMBaseModem *self);
+MMAtSerialPort *mm_base_modem_peek_port_gps_control (MMBaseModem *self);
+MMGpsSerialPort *mm_base_modem_peek_port_gps (MMBaseModem *self);
+MMQmiPort *mm_base_modem_peek_port_qmi (MMBaseModem *self);
+MMQmiPort *mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self, MMPort *data, GError **error);
+MMAtSerialPort *mm_base_modem_peek_best_at_port (MMBaseModem *self, GError **error);
+MMPort *mm_base_modem_peek_best_data_port (MMBaseModem *self);
+GList *mm_base_modem_peek_data_ports (MMBaseModem *self);
MMAtSerialPort *mm_base_modem_get_port_primary (MMBaseModem *self);
MMAtSerialPort *mm_base_modem_get_port_secondary (MMBaseModem *self);
@@ -128,6 +129,7 @@ MMQcdmSerialPort *mm_base_modem_get_port_qcdm (MMBaseModem *self);
MMAtSerialPort *mm_base_modem_get_port_gps_control (MMBaseModem *self);
MMGpsSerialPort *mm_base_modem_get_port_gps (MMBaseModem *self);
MMQmiPort *mm_base_modem_get_port_qmi (MMBaseModem *self);
+MMQmiPort *mm_base_modem_get_port_qmi_for_data (MMBaseModem *self, MMPort *data, GError **error);
MMAtSerialPort *mm_base_modem_get_best_at_port (MMBaseModem *self, GError **error);
MMPort *mm_base_modem_get_best_data_port (MMBaseModem *self);
GList *mm_base_modem_get_data_ports (MMBaseModem *self);
--
1.7.11.4
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]