From 71801cf3a9ee5cda62d830c46290ec77722eecb8 Mon Sep 17 00:00:00 2001 From: Lukas Arnold Date: Tue, 8 Nov 2022 22:10:54 +0100 Subject: libqmi-glib: allow qmux connection over unix domain socket --- src/libqmi-glib/qmi-endpoint-qmux.c | 67 +++++++++++++++++++++++++++++++++++++ src/libqmi-glib/qmi-helpers.c | 4 +++ src/libqmi-glib/qmi-helpers.h | 6 ++++ 3 files changed, 77 insertions(+) (limited to 'src') diff --git a/src/libqmi-glib/qmi-endpoint-qmux.c b/src/libqmi-glib/qmi-endpoint-qmux.c index 444b8f6c..3a4cbdee 100644 --- a/src/libqmi-glib/qmi-endpoint-qmux.c +++ b/src/libqmi-glib/qmi-endpoint-qmux.c @@ -36,6 +36,7 @@ #include "qmi-ctl.h" #include "qmi-errors.h" #include "qmi-error-types.h" +#include "qmi-helpers.h" G_DEFINE_TYPE (QmiEndpointQmux, qmi_endpoint_qmux, QMI_TYPE_ENDPOINT) @@ -342,6 +343,64 @@ create_iostream_with_socket (GTask *task) setup_iostream (task); } +static void +create_iostream_with_socket_direct (GTask *task) +{ + QmiEndpointQmux *self; + QmiFile *file; + GSocketAddress *socket_address; + GError *error = NULL; + + self = g_task_get_source_object (task); + + /* Create socket client */ + self->priv->socket_client = g_socket_client_new (); + g_socket_client_set_family (self->priv->socket_client, G_SOCKET_FAMILY_UNIX); + g_socket_client_set_socket_type (self->priv->socket_client, G_SOCKET_TYPE_STREAM); + g_socket_client_set_protocol (self->priv->socket_client, G_SOCKET_PROTOCOL_DEFAULT); + + /* Setup socket address (using a system path) */ + g_object_get (self, QMI_ENDPOINT_FILE, &file, NULL); + socket_address = g_unix_socket_address_new_with_type ( + qmi_file_get_path (file), + -1, + G_UNIX_SOCKET_ADDRESS_PATH); + + /* Connect to address */ + self->priv->socket_connection = g_socket_client_connect ( + self->priv->socket_client, + G_SOCKET_CONNECTABLE (socket_address), + NULL, + &error); + g_object_unref (socket_address); + + /* Display an error if the socket is not reachable */ + if (!self->priv->socket_connection) { + g_task_return_new_error (task, + QMI_CORE_ERROR, + QMI_CORE_ERROR_FAILED, + "Cannot connect to the socket '%s': '%s'", + qmi_file_get_path (file), + error->message); + g_object_unref (file); + g_object_unref (task); + return; + } + + g_object_unref (file); + + /* Use the input and output streams of the socket */ + self->priv->istream = g_io_stream_get_input_stream (G_IO_STREAM (self->priv->socket_connection)); + if (self->priv->istream) + g_object_ref (self->priv->istream); + + self->priv->ostream = g_io_stream_get_output_stream (G_IO_STREAM (self->priv->socket_connection)); + if (self->priv->ostream) + g_object_ref (self->priv->ostream); + + setup_iostream (task); +} + static void endpoint_open (QmiEndpoint *endpoint, gboolean use_proxy, @@ -352,6 +411,7 @@ endpoint_open (QmiEndpoint *endpoint, { QmiEndpointQmux *self; QmuxDeviceOpenContext *ctx; + QmiFile *file; GTask *task; ctx = g_slice_new (QmuxDeviceOpenContext); @@ -373,10 +433,17 @@ endpoint_open (QmiEndpoint *endpoint, return; } + /* Get the file name to determine whether a unix domain socket should be used instead of a device file */ + g_object_get (self, QMI_ENDPOINT_FILE, &file, NULL); + if (use_proxy) create_iostream_with_socket (task); + else if (g_strrstr (qmi_file_get_path (file), QMI_QMUX_SOCKET_FILE_NAME)) + create_iostream_with_socket_direct (task); else create_iostream_with_fd (task); + + g_object_unref (file); } /*****************************************************************************/ diff --git a/src/libqmi-glib/qmi-helpers.c b/src/libqmi-glib/qmi-helpers.c index 4d93342c..2cd433fb 100644 --- a/src/libqmi-glib/qmi-helpers.c +++ b/src/libqmi-glib/qmi-helpers.c @@ -520,6 +520,10 @@ qmi_helpers_get_transport_type (const gchar *path, if (g_file_test (rpmsg_sysfs_path, G_FILE_TEST_EXISTS)) return QMI_HELPERS_TRANSPORT_TYPE_QMUX; + /* Allow libqmi to connect directly to a unix domain socket with a specific file name */ + if (g_strrstr (device_basename, QMI_QMUX_SOCKET_FILE_NAME)) + return QMI_HELPERS_TRANSPORT_TYPE_QMUX; + g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED, "unexpected port subsystem"); return QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN; diff --git a/src/libqmi-glib/qmi-helpers.h b/src/libqmi-glib/qmi-helpers.h index 14fa6234..48b9f6df 100644 --- a/src/libqmi-glib/qmi-helpers.h +++ b/src/libqmi-glib/qmi-helpers.h @@ -60,6 +60,12 @@ typedef enum { QMI_HELPERS_TRANSPORT_TYPE_MBIM, } QmiHelpersTransportType; +/* + * Symbol defining the file name for a unix domain socket used instead of a device file. + * The unix domain socket is addressed with the QMUX protocol. + */ +#define QMI_QMUX_SOCKET_FILE_NAME "qmux_socket" + G_GNUC_INTERNAL QmiHelpersTransportType qmi_helpers_get_transport_type (const gchar *path, GError **error); -- cgit v1.2.1