aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c3
-rw-r--r--src/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c3
-rw-r--r--src/plugins/fibocom/mm-port-mbim-fibocom.c278
-rw-r--r--src/plugins/fibocom/mm-port-mbim-fibocom.h59
-rw-r--r--src/plugins/fibocom/mm-shared-fibocom.c35
-rw-r--r--src/plugins/fibocom/mm-shared-fibocom.h7
-rw-r--r--src/plugins/meson.build1
-rw-r--r--src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c3
8 files changed, 389 insertions, 0 deletions
diff --git a/src/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c b/src/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c
index df66da3d..189af6cc 100644
--- a/src/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c
+++ b/src/plugins/fibocom/mm-broadband-modem-mbim-fibocom.c
@@ -107,7 +107,10 @@ shared_fibocom_init (MMSharedFibocom *iface)
static void
mm_broadband_modem_mbim_fibocom_class_init (MMBroadbandModemMbimFibocomClass *klass)
{
+ MMBaseModemClass *base_modem_class = MM_BASE_MODEM_CLASS (klass);
MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass);
+ base_modem_class->create_usbmisc_port = mm_shared_fibocom_create_usbmisc_port;
+ base_modem_class->create_wwan_port = mm_shared_fibocom_create_wwan_port;
broadband_modem_class->setup_ports = mm_shared_fibocom_setup_ports;
}
diff --git a/src/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c b/src/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c
index 239247a2..86afdfdf 100644
--- a/src/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c
+++ b/src/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c
@@ -110,7 +110,10 @@ shared_fibocom_init (MMSharedFibocom *iface)
static void
mm_broadband_modem_mbim_xmm_fibocom_class_init (MMBroadbandModemMbimXmmFibocomClass *klass)
{
+ MMBaseModemClass *base_modem_class = MM_BASE_MODEM_CLASS (klass);
MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass);
+ base_modem_class->create_usbmisc_port = mm_shared_fibocom_create_usbmisc_port;
+ base_modem_class->create_wwan_port = mm_shared_fibocom_create_wwan_port;
broadband_modem_class->setup_ports = mm_shared_fibocom_setup_ports;
}
diff --git a/src/plugins/fibocom/mm-port-mbim-fibocom.c b/src/plugins/fibocom/mm-port-mbim-fibocom.c
new file mode 100644
index 00000000..e7d26ed0
--- /dev/null
+++ b/src/plugins/fibocom/mm-port-mbim-fibocom.c
@@ -0,0 +1,278 @@
+/* -*- 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) 2024 Google, Inc.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <ModemManager.h>
+#include <mm-errors-types.h>
+
+#include "mm-serial-parsers.h"
+#include "mm-iface-port-at.h"
+#include "mm-port-mbim-fibocom.h"
+#include "mm-log-object.h"
+
+static void iface_port_at_init (MMIfacePortAt *iface);
+
+G_DEFINE_TYPE_EXTENDED (MMPortMbimFibocom, mm_port_mbim_fibocom, MM_TYPE_PORT_MBIM, 0,
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_PORT_AT, iface_port_at_init))
+
+typedef enum {
+ FEATURE_SUPPORT_UNKNOWN,
+ FEATURE_NOT_SUPPORTED,
+ FEATURE_SUPPORTED
+} FeatureSupport;
+
+struct _MMPortMbimFibocomPrivate {
+ FeatureSupport at_over_mbim;
+ gpointer parser;
+};
+
+/*****************************************************************************/
+
+static gboolean
+iface_port_at_check_support (MMIfacePortAt *_self,
+ gboolean *out_supported,
+ GError **error)
+{
+ MMPortMbimFibocom *self = MM_PORT_MBIM_FIBOCOM (_self);
+
+ g_assert (out_supported);
+
+ if (self->priv->at_over_mbim == FEATURE_SUPPORT_UNKNOWN) {
+ /* First time check */
+ if (!mm_port_mbim_is_open (MM_PORT_MBIM (self))) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
+ "Couldn't check AT support: MBIM port is closed");
+ return FALSE;
+ }
+
+ if (!mm_port_mbim_supports_command (MM_PORT_MBIM (self), MBIM_SERVICE_FIBOCOM, MBIM_CID_FIBOCOM_AT_COMMAND)) {
+ mm_obj_msg (self, "MBIM device is not AT capable");
+ self->priv->at_over_mbim = FEATURE_NOT_SUPPORTED;
+ } else {
+ mm_obj_msg (self, "MBIM device is AT capable");
+ self->priv->at_over_mbim = FEATURE_SUPPORTED;
+ }
+ }
+
+ *out_supported = (self->priv->at_over_mbim == FEATURE_SUPPORTED);
+ return TRUE;
+}
+
+/*****************************************************************************/
+/* AT command */
+
+static gchar *
+iface_port_at_command_finish (MMIfacePortAt *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+debug_log (MMPortMbimFibocom *self,
+ const gchar *prefix,
+ const guint8 *buf,
+ gsize len)
+{
+ g_autoptr(GString) debug = NULL;
+ const guint8 *s;
+
+ debug = g_string_new (prefix);
+ g_string_append (debug, " '");
+
+ s = buf;
+ while (len--) {
+ if (g_ascii_isprint ((gchar)*s))
+ g_string_append_c (debug, (gchar)*s);
+ else if (*s == '\r')
+ g_string_append (debug, "<CR>");
+ else if (*s == '\n')
+ g_string_append (debug, "<LF>");
+ else
+ g_string_append_printf (debug, "\\%u", (guint8) (*s & 0xFF));
+ s++;
+ }
+
+ g_string_append_c (debug, '\'');
+ mm_obj_dbg (self, "%s", debug->str);
+}
+
+static void
+at_command_ready (MbimDevice *device,
+ GAsyncResult *res,
+ GTask *task)
+{
+ g_autoptr(GError) error = NULL;
+ MMPortMbimFibocom *self;
+ guint32 ret_size = 0;
+ const guint8 *ret_str = NULL;
+ g_autoptr(MbimMessage) response = NULL;
+ GString *string;
+
+ self = g_task_get_source_object (task);
+
+ response = mbim_device_command_finish (device, res, &error);
+ if (!response ||
+ !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
+ !mbim_message_fibocom_at_command_response_parse (
+ response,
+ &ret_size,
+ &ret_str,
+ &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ debug_log (self, "<--", ret_str, ret_size);
+
+ if (G_UNLIKELY (!self->priv->parser))
+ self->priv->parser = mm_serial_parser_v1_new ();
+
+ /* Prepare the GString to pass to the parser. We add an explicit leading CRLF
+ * sequence only because it is what the parser expects, so that we don't need
+ * to do major changes to handle that case. */
+ string = g_string_sized_new (ret_size + 3);
+ g_string_append (string, "\r\n");
+ g_string_append_len (string, (const gchar *) ret_str, ret_size);
+
+ if (!mm_serial_parser_v1_parse (self->priv->parser, string, self, &error)) {
+ if (error)
+ g_task_return_error (task, error);
+ else
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Incomplete response");
+ g_string_free (string, TRUE);
+ g_object_unref (task);
+ return;
+ }
+
+ g_task_return_pointer (task, g_string_free (string, FALSE), g_free);
+ g_object_unref (task);
+}
+
+static GByteArray *
+at_command_to_byte_array (const gchar *command,
+ gboolean is_raw)
+{
+ GByteArray *buf;
+ int cmdlen;
+
+ cmdlen = strlen (command);
+ buf = g_byte_array_sized_new (cmdlen + 4);
+
+ if (!is_raw) {
+ /* Make sure there's an AT in the front */
+ if (!g_str_has_prefix (command, "AT"))
+ g_byte_array_append (buf, (const guint8 *) "AT", 2);
+ }
+
+ g_byte_array_append (buf, (const guint8 *) command, cmdlen);
+
+ if (!is_raw) {
+ /* Make sure there's a trailing carriage return */
+ if ((cmdlen == 0) ||
+ (command[cmdlen - 1] != '\r' && (cmdlen == 1 || command[cmdlen - 2] != '\r')))
+ g_byte_array_append (buf, (const guint8 *) "\r", 1);
+ /* Make sure there's a trailing line-feed */
+ if ((cmdlen == 0) ||
+ (command[cmdlen - 1] != '\n' && (cmdlen == 1 || command[cmdlen - 2] != '\n')))
+ g_byte_array_append (buf, (const guint8 *) "\n", 1);
+ }
+
+ return buf;
+}
+
+static void
+iface_port_at_command (MMIfacePortAt *self,
+ const gchar *command,
+ guint32 timeout_seconds,
+ gboolean is_raw,
+ gboolean allow_cached, /* ignored */
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(MbimMessage) request = NULL;
+ g_autoptr(GByteArray) buffer = NULL;
+ GTask *task;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ buffer = at_command_to_byte_array (command, is_raw);
+
+ debug_log (MM_PORT_MBIM_FIBOCOM (self), "-->", buffer->data, buffer->len);
+
+ request = mbim_message_fibocom_at_command_set_new (buffer->len, (const guint8 *)buffer->data, NULL);
+ mbim_device_command (mm_port_mbim_peek_device (MM_PORT_MBIM (self)),
+ request,
+ timeout_seconds,
+ cancellable,
+ (GAsyncReadyCallback)at_command_ready,
+ task);
+}
+
+/*****************************************************************************/
+
+MMPortMbimFibocom *
+mm_port_mbim_fibocom_new (const gchar *name,
+ MMPortSubsys subsys)
+{
+ return MM_PORT_MBIM_FIBOCOM (g_object_new (MM_TYPE_PORT_MBIM_FIBOCOM,
+ MM_PORT_DEVICE, name,
+ MM_PORT_SUBSYS, subsys,
+ MM_PORT_TYPE, MM_PORT_TYPE_MBIM,
+ NULL));
+}
+
+static void
+mm_port_mbim_fibocom_init (MMPortMbimFibocom *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_PORT_MBIM_FIBOCOM, MMPortMbimFibocomPrivate);
+ self->priv->at_over_mbim = FEATURE_SUPPORT_UNKNOWN;
+}
+
+static void
+finalize (GObject *object)
+{
+ MMPortMbimFibocom *self = MM_PORT_MBIM_FIBOCOM (object);
+
+ if (self->priv->parser)
+ mm_serial_parser_v1_destroy (self->priv->parser);
+
+ G_OBJECT_CLASS (mm_port_mbim_fibocom_parent_class)->finalize (object);
+}
+
+static void
+iface_port_at_init (MMIfacePortAt *iface)
+{
+ iface->check_support = iface_port_at_check_support;
+ iface->command = iface_port_at_command;
+ iface->command_finish = iface_port_at_command_finish;
+}
+
+static void
+mm_port_mbim_fibocom_class_init (MMPortMbimFibocomClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMPortMbimFibocomPrivate));
+
+ object_class->finalize = finalize;
+}
diff --git a/src/plugins/fibocom/mm-port-mbim-fibocom.h b/src/plugins/fibocom/mm-port-mbim-fibocom.h
new file mode 100644
index 00000000..f7104cd6
--- /dev/null
+++ b/src/plugins/fibocom/mm-port-mbim-fibocom.h
@@ -0,0 +1,59 @@
+/* -*- 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) 2024 Google, Inc.
+ */
+
+#ifndef MM_PORT_MBIM_FIBOCOM_H
+#define MM_PORT_MBIM_FIBOCOM_H
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include <libmbim-glib.h>
+
+#if defined WITH_QMI
+# include <libqmi-glib.h>
+#endif
+
+#include "mm-port-mbim.h"
+
+#define MM_TYPE_PORT_MBIM_FIBOCOM (mm_port_mbim_fibocom_get_type ())
+#define MM_PORT_MBIM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PORT_MBIM_FIBOCOM, MMPortMbimFibocom))
+#define MM_PORT_MBIM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PORT_MBIM_FIBOCOM, MMPortMbimFibocomClass))
+#define MM_IS_PORT_MBIM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PORT_MBIM_FIBOCOM))
+#define MM_IS_PORT_MBIM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PORT_MBIM_FIBOCOM))
+#define MM_PORT_MBIM_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PORT_MBIM_FIBOCOM, MMPortMbimFibocomClass))
+
+typedef struct _MMPortMbimFibocom MMPortMbimFibocom;
+typedef struct _MMPortMbimFibocomClass MMPortMbimFibocomClass;
+typedef struct _MMPortMbimFibocomPrivate MMPortMbimFibocomPrivate;
+
+struct _MMPortMbimFibocom {
+ MMPortMbim parent;
+ MMPortMbimFibocomPrivate *priv;
+};
+
+struct _MMPortMbimFibocomClass {
+ MMPortMbimClass parent;
+};
+
+GType mm_port_mbim_fibocom_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMPortMbimFibocom, g_object_unref)
+
+MMPortMbimFibocom *mm_port_mbim_fibocom_new (const gchar *name,
+ MMPortSubsys subsys);
+
+#endif /* MM_PORT_MBIM_FIBOCOM_H */
diff --git a/src/plugins/fibocom/mm-shared-fibocom.c b/src/plugins/fibocom/mm-shared-fibocom.c
index 50ac892e..562e1f79 100644
--- a/src/plugins/fibocom/mm-shared-fibocom.c
+++ b/src/plugins/fibocom/mm-shared-fibocom.c
@@ -28,6 +28,7 @@
#include "mm-iface-modem.h"
#include "mm-iface-modem-3gpp.h"
#include "mm-shared-fibocom.h"
+#include "mm-port-mbim-fibocom.h"
#include "mm-base-modem-at.h"
/*****************************************************************************/
@@ -83,6 +84,40 @@ get_private (MMSharedFibocom *self)
/*****************************************************************************/
+MMPort *
+mm_shared_fibocom_create_usbmisc_port (MMBaseModem *self,
+ const gchar *name,
+ MMPortType ptype)
+{
+ Private *priv;
+
+ priv = get_private (MM_SHARED_FIBOCOM (self));
+ if (ptype == MM_PORT_TYPE_MBIM) {
+ mm_obj_dbg (self, "creating fibocom-specific MBIM port...");
+ return MM_PORT (mm_port_mbim_fibocom_new (name, MM_PORT_SUBSYS_USBMISC));
+ }
+
+ return priv->class_parent->create_usbmisc_port (self, name, ptype);
+}
+
+MMPort *
+mm_shared_fibocom_create_wwan_port (MMBaseModem *self,
+ const gchar *name,
+ MMPortType ptype)
+{
+ Private *priv;
+
+ priv = get_private (MM_SHARED_FIBOCOM (self));
+ if (ptype == MM_PORT_TYPE_MBIM) {
+ mm_obj_dbg (self, "creating fibocom-specific MBIM port...");
+ return MM_PORT (mm_port_mbim_fibocom_new (name, MM_PORT_SUBSYS_WWAN));
+ }
+
+ return priv->class_parent->create_wwan_port (self, name, ptype);
+}
+
+/*****************************************************************************/
+
void
mm_shared_fibocom_setup_ports (MMBroadbandModem *self)
{
diff --git a/src/plugins/fibocom/mm-shared-fibocom.h b/src/plugins/fibocom/mm-shared-fibocom.h
index ac2adb3b..cd763937 100644
--- a/src/plugins/fibocom/mm-shared-fibocom.h
+++ b/src/plugins/fibocom/mm-shared-fibocom.h
@@ -48,6 +48,13 @@ GType mm_shared_fibocom_get_type (void);
void mm_shared_fibocom_setup_ports (MMBroadbandModem *self);
+MMPort *mm_shared_fibocom_create_usbmisc_port (MMBaseModem *self,
+ const gchar *name,
+ MMPortType ptype);
+MMPort *mm_shared_fibocom_create_wwan_port (MMBaseModem *self,
+ const gchar *name,
+ MMPortType ptype);
+
void mm_shared_fibocom_set_initial_eps_bearer_settings (MMIfaceModem3gpp *self,
MMBearerProperties *config,
GAsyncReadyCallback callback,
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index dd8fd131..30379fb4 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -73,6 +73,7 @@ if plugins_shared['fibocom']
c_args = '-DMM_MODULE_NAME="shared-fibocom"'
sources = files(
+ 'fibocom/mm-port-mbim-fibocom.c',
'fibocom/mm-shared.c',
'fibocom/mm-shared-fibocom.c',
)
diff --git a/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c b/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
index 08d5441a..67ef8dcf 100644
--- a/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
+++ b/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
@@ -316,9 +316,12 @@ static void
mm_broadband_modem_mbim_mtk_fibocom_class_init (MMBroadbandModemMbimMtkFibocomClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMBaseModemClass *base_modem_class = MM_BASE_MODEM_CLASS (klass);
MMBroadbandModemMbimClass *broadband_modem_mbim_class = MM_BROADBAND_MODEM_MBIM_CLASS (klass);
g_type_class_add_private (object_class, sizeof (MMBroadbandModemMbimMtkFibocomPrivate));
+ base_modem_class->create_usbmisc_port = mm_shared_fibocom_create_usbmisc_port;
+ base_modem_class->create_wwan_port = mm_shared_fibocom_create_wwan_port;
broadband_modem_mbim_class->normalize_nw_error = normalize_nw_error;
}