diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2022-12-08 13:37:55 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2023-01-03 13:56:25 +0000 |
commit | e14b904cbd6816cb0227d519d308ae71ddaf6e07 (patch) | |
tree | 4997ab68cc606fdf4d72a571e821cec0c8df42ef /src/plugins/qcom-soc | |
parent | 072d7ac9065f444e83b390a1e2af5471ac0d48f6 (diff) |
build: move plugins directory to src/plugins
We are going to allow including the plugin sources built within the
ModemManager daemon binary; moving the sources within the daemon
sources directory makes it easier.
Diffstat (limited to 'src/plugins/qcom-soc')
-rw-r--r-- | src/plugins/qcom-soc/77-mm-qcom-soc.rules | 40 | ||||
-rw-r--r-- | src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.c | 176 | ||||
-rw-r--r-- | src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.h | 49 | ||||
-rw-r--r-- | src/plugins/qcom-soc/mm-plugin-qcom-soc.c | 98 | ||||
-rw-r--r-- | src/plugins/qcom-soc/mm-plugin-qcom-soc.h | 40 |
5 files changed, 403 insertions, 0 deletions
diff --git a/src/plugins/qcom-soc/77-mm-qcom-soc.rules b/src/plugins/qcom-soc/77-mm-qcom-soc.rules new file mode 100644 index 00000000..9719f96f --- /dev/null +++ b/src/plugins/qcom-soc/77-mm-qcom-soc.rules @@ -0,0 +1,40 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="add|change|move|bind", GOTO="mm_qcom_soc_end" + +# Process only known wwan, net and rpmsg ports +SUBSYSTEM=="net", DRIVERS=="bam-dmux", GOTO="mm_qcom_soc_process" +SUBSYSTEM=="net", DRIVERS=="ipa", GOTO="mm_qcom_soc_process" +SUBSYSTEM=="wwan", DRIVERS=="qcom-q6v5-mss", GOTO="mm_qcom_soc_process" +SUBSYSTEM=="rpmsg", DRIVERS=="qcom-q6v5-mss", GOTO="mm_qcom_soc_process" +GOTO="mm_qcom_soc_end" + +LABEL="mm_qcom_soc_process" + +# Flag the port as being part of the SoC +ENV{ID_MM_QCOM_SOC}="1" + +# +# Add a common physdev UID to all ports in the Qualcomm SoC, so that they +# are all bound together to the same modem object. +# +# The MSM8916, MSM8974, .... Qualcomm SoCs use the combination of RPMSG/WWAN +# based control ports plus BAM-DMUX based network ports. +# +ENV{ID_MM_PHYSDEV_UID}="qcom-soc" + +# port type hints for the rpmsgexport-ed ports +SUBSYSTEM=="rpmsg", ATTR{name}=="DATA*", ATTR{name}=="*_CNTL", ENV{ID_MM_PORT_TYPE_QMI}="1" +SUBSYSTEM=="rpmsg", ATTR{name}=="DATA*", ATTR{name}!="*_CNTL", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" + +# ignore every other port without explicit hints +SUBSYSTEM=="rpmsg", ENV{ID_MM_PORT_TYPE_QMI}!="1", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}!="1", ENV{ID_MM_PORT_IGNORE}="1" + +# explicitly ignore ports intended for USB tethering (DATA40, DATA40_CNTL) +SUBSYSTEM=="rpmsg", ATTR{name}=="DATA40*", ENV{ID_MM_PORT_IGNORE}="1" +KERNEL=="rmnet_usb*", ENV{ID_MM_PORT_IGNORE}="1" + +# flag all rpmsg ports under this plugin as candidate +KERNEL=="rpmsg*", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1" + +LABEL="mm_qcom_soc_end" diff --git a/src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.c b/src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.c new file mode 100644 index 00000000..21d62c12 --- /dev/null +++ b/src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.c @@ -0,0 +1,176 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2020 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "ModemManager.h" +#include "mm-log.h" +#include "mm-iface-modem.h" +#include "mm-broadband-modem-qmi-qcom-soc.h" + +G_DEFINE_TYPE (MMBroadbandModemQmiQcomSoc, mm_broadband_modem_qmi_qcom_soc, MM_TYPE_BROADBAND_MODEM_QMI) + +/*****************************************************************************/ + +static const QmiSioPort sio_port_per_port_number[] = { + QMI_SIO_PORT_A2_MUX_RMNET0, + QMI_SIO_PORT_A2_MUX_RMNET1, + QMI_SIO_PORT_A2_MUX_RMNET2, + QMI_SIO_PORT_A2_MUX_RMNET3, + QMI_SIO_PORT_A2_MUX_RMNET4, + QMI_SIO_PORT_A2_MUX_RMNET5, + QMI_SIO_PORT_A2_MUX_RMNET6, + QMI_SIO_PORT_A2_MUX_RMNET7 +}; + +static MMPortQmi * +peek_port_qmi_for_data_bam_dmux (MMBroadbandModemQmi *self, + MMPort *data, + MMQmiDataEndpoint *out_endpoint, + GError **error) +{ + MMPortQmi *found = NULL; + MMKernelDevice *net_port; + gint net_port_number; + + net_port = mm_port_peek_kernel_device (data); + + /* The dev_port notified by the bam-dmux driver indicates which SIO port we should be using */ + net_port_number = mm_kernel_device_get_attribute_as_int (net_port, "dev_port"); + if (net_port_number < 0 || net_port_number >= (gint) G_N_ELEMENTS (sio_port_per_port_number)) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_NOT_FOUND, + "Couldn't find SIO port number for 'net/%s'", + mm_port_get_device (data)); + return NULL; + } + + /* Find one QMI port, we don't care which one */ + found = mm_broadband_modem_qmi_peek_port_qmi (self); + + if (!found) + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_NOT_FOUND, + "Couldn't find any QMI port for 'net/%s'", + mm_port_get_device (data)); + else if (out_endpoint) { + /* WDS Bind (Mux) Data Port must be called with the correct endpoint + * interface number/SIO port to make multiplexing work with BAM-DMUX */ + out_endpoint->type = QMI_DATA_ENDPOINT_TYPE_BAM_DMUX; + out_endpoint->interface_number = net_port_number; + out_endpoint->sio_port = sio_port_per_port_number[net_port_number]; + } + + return found; +} + +static MMPortQmi * +peek_port_qmi_for_data_ipa (MMBroadbandModemQmi *self, + MMPort *data, + MMQmiDataEndpoint *out_endpoint, + GError **error) +{ + MMPortQmi *found = NULL; + + /* when using IPA, we have a main network interface that will be multiplexed + * to create link interfaces. We can assume any of the available QMI ports is + * able to manage that. */ + + found = mm_broadband_modem_qmi_peek_port_qmi (self); + + if (!found) + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_NOT_FOUND, + "Couldn't find any QMI port for 'net/%s'", + mm_port_get_device (data)); + else if (out_endpoint) + mm_port_qmi_get_endpoint_info (found, out_endpoint); + + return found; +} + +static MMPortQmi * +peek_port_qmi_for_data (MMBroadbandModemQmi *self, + MMPort *data, + MMQmiDataEndpoint *out_endpoint, + GError **error) +{ + MMKernelDevice *net_port; + const gchar *net_port_driver; + + g_assert (MM_IS_BROADBAND_MODEM_QMI (self)); + g_assert (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET); + + net_port = mm_port_peek_kernel_device (data); + net_port_driver = mm_kernel_device_get_driver (net_port); + + if (g_strcmp0 (net_port_driver, "ipa") == 0) + return peek_port_qmi_for_data_ipa (self, data, out_endpoint, error); + + if (g_strcmp0 (net_port_driver, "bam-dmux") == 0) + return peek_port_qmi_for_data_bam_dmux (self, data, out_endpoint, error); + + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Unsupported QMI kernel driver for 'net/%s': %s", + mm_port_get_device (data), + net_port_driver); + return NULL; +} + +/*****************************************************************************/ + +MMBroadbandModemQmiQcomSoc * +mm_broadband_modem_qmi_qcom_soc_new (const gchar *device, + const gchar **drivers, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id) +{ + return g_object_new (MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, + MM_BASE_MODEM_DEVICE, device, + MM_BASE_MODEM_DRIVERS, drivers, + MM_BASE_MODEM_PLUGIN, plugin, + MM_BASE_MODEM_VENDOR_ID, vendor_id, + MM_BASE_MODEM_PRODUCT_ID, product_id, + /* QMI bearer supports NET only */ + MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, + MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, + MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, + NULL); +} + +static void +mm_broadband_modem_qmi_qcom_soc_init (MMBroadbandModemQmiQcomSoc *self) +{ +} + +static void +mm_broadband_modem_qmi_qcom_soc_class_init (MMBroadbandModemQmiQcomSocClass *klass) +{ + MMBroadbandModemQmiClass *broadband_modem_qmi_class = MM_BROADBAND_MODEM_QMI_CLASS (klass); + + broadband_modem_qmi_class->peek_port_qmi_for_data = peek_port_qmi_for_data; +} diff --git a/src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.h b/src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.h new file mode 100644 index 00000000..92c37beb --- /dev/null +++ b/src/plugins/qcom-soc/mm-broadband-modem-qmi-qcom-soc.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2020 Aleksander Morgado <aleksander@aleksander.es> + */ + +#ifndef MM_BROADBAND_MODEM_QMI_QCOM_SOC_H +#define MM_BROADBAND_MODEM_QMI_QCOM_SOC_H + +#include "mm-broadband-modem-qmi.h" + +#define MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC (mm_broadband_modem_qmi_qcom_soc_get_type ()) +#define MM_BROADBAND_MODEM_QMI_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, MMBroadbandModemQmiQcomSoc)) +#define MM_BROADBAND_MODEM_QMI_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, MMBroadbandModemQmiQcomSocClass)) +#define MM_IS_BROADBAND_MODEM_QMI_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC)) +#define MM_IS_BROADBAND_MODEM_QMI_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC)) +#define MM_BROADBAND_MODEM_QMI_QCOM_SOC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_QMI_QCOM_SOC, MMBroadbandModemQmiQcomSocClass)) + +typedef struct _MMBroadbandModemQmiQcomSoc MMBroadbandModemQmiQcomSoc; +typedef struct _MMBroadbandModemQmiQcomSocClass MMBroadbandModemQmiQcomSocClass; +typedef struct _MMBroadbandModemQmiQcomSocPrivate MMBroadbandModemQmiQcomSocPrivate; + +struct _MMBroadbandModemQmiQcomSoc { + MMBroadbandModemQmi parent; + MMBroadbandModemQmiQcomSocPrivate *priv; +}; + +struct _MMBroadbandModemQmiQcomSocClass{ + MMBroadbandModemQmiClass parent; +}; + +GType mm_broadband_modem_qmi_qcom_soc_get_type (void); + +MMBroadbandModemQmiQcomSoc *mm_broadband_modem_qmi_qcom_soc_new (const gchar *device, + const gchar **drivers, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id); + +#endif /* MM_BROADBAND_MODEM_QMI_QCOM_SOC_H */ diff --git a/src/plugins/qcom-soc/mm-plugin-qcom-soc.c b/src/plugins/qcom-soc/mm-plugin-qcom-soc.c new file mode 100644 index 00000000..ae844dd6 --- /dev/null +++ b/src/plugins/qcom-soc/mm-plugin-qcom-soc.c @@ -0,0 +1,98 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2020 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include <string.h> +#include <termios.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <time.h> + +#include <gmodule.h> + +#define _LIBMM_INSIDE_MM +#include <libmm-glib.h> + +#include "mm-plugin-qcom-soc.h" +#include "mm-broadband-modem-qmi-qcom-soc.h" +#include "mm-log-object.h" + +G_DEFINE_TYPE (MMPluginQcomSoc, mm_plugin_qcom_soc, MM_TYPE_PLUGIN) + +MM_PLUGIN_DEFINE_MAJOR_VERSION +MM_PLUGIN_DEFINE_MINOR_VERSION + +/*****************************************************************************/ + +static MMBaseModem * +create_modem (MMPlugin *self, + const gchar *uid, + const gchar **drivers, + guint16 vendor, + guint16 product, + guint16 subsystem_vendor, + GList *probes, + GError **error) +{ + if (!mm_port_probe_list_has_qmi_port (probes)) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Unsupported device: at least a QMI port is required"); + return NULL; + } + + mm_obj_dbg (self, "Qualcomm SoC modem found..."); + return MM_BASE_MODEM (mm_broadband_modem_qmi_qcom_soc_new (uid, + drivers, + mm_plugin_get_name (self), + vendor, + product)); +} + +/*****************************************************************************/ + +G_MODULE_EXPORT MMPlugin * +mm_plugin_create (void) +{ + static const gchar *subsystems[] = { "wwan", "rpmsg", "net", "qrtr", NULL }; + static const gchar *udev_tags[] = { + "ID_MM_QCOM_SOC", + NULL + }; + + return MM_PLUGIN ( + g_object_new (MM_TYPE_PLUGIN_QCOM_SOC, + MM_PLUGIN_NAME, MM_MODULE_NAME, + MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, + MM_PLUGIN_ALLOWED_AT, TRUE, + MM_PLUGIN_ALLOWED_QMI, TRUE, + MM_PLUGIN_ALLOWED_UDEV_TAGS, udev_tags, + NULL)); +} + +static void +mm_plugin_qcom_soc_init (MMPluginQcomSoc *self) +{ +} + +static void +mm_plugin_qcom_soc_class_init (MMPluginQcomSocClass *klass) +{ + MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); + + plugin_class->create_modem = create_modem; +} diff --git a/src/plugins/qcom-soc/mm-plugin-qcom-soc.h b/src/plugins/qcom-soc/mm-plugin-qcom-soc.h new file mode 100644 index 00000000..54da154f --- /dev/null +++ b/src/plugins/qcom-soc/mm-plugin-qcom-soc.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2020 Aleksander Morgado <aleksander@aleksander.es> + */ + +#ifndef MM_PLUGIN_QCOM_SOC_H +#define MM_PLUGIN_QCOM_SOC_H + +#include "mm-plugin.h" + +#define MM_TYPE_PLUGIN_QCOM_SOC (mm_plugin_qcom_soc_get_type ()) +#define MM_PLUGIN_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_QCOM_SOC, MMPluginQcomSoc)) +#define MM_PLUGIN_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_QCOM_SOC, MMPluginQcomSocClass)) +#define MM_IS_PLUGIN_QCOM_SOC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_QCOM_SOC)) +#define MM_IS_PLUGIN_QCOM_SOC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_QCOM_SOC)) +#define MM_PLUGIN_QCOM_SOC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_QCOM_SOC, MMPluginQcomSocClass)) + +typedef struct { + MMPlugin parent; +} MMPluginQcomSoc; + +typedef struct { + MMPluginClass parent; +} MMPluginQcomSocClass; + +GType mm_plugin_qcom_soc_get_type (void); + +G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); + +#endif /* MM_PLUGIN_QCOM_SOC_H */ |