port-qmi: add support for QRTR
Extend mm-port-qmi to accept a QRTR node to work with modems using the QRTR protocol.
This commit is contained in:

committed by
Aleksander Morgado

parent
312f753046
commit
ec375bd959
@@ -1560,6 +1560,7 @@ mm_port_subsys_to_qmi_endpoint_type (MMPortSubsys subsys)
|
|||||||
case MM_PORT_SUBSYS_USBMISC:
|
case MM_PORT_SUBSYS_USBMISC:
|
||||||
return QMI_DATA_ENDPOINT_TYPE_HSUSB;
|
return QMI_DATA_ENDPOINT_TYPE_HSUSB;
|
||||||
case MM_PORT_SUBSYS_RPMSG:
|
case MM_PORT_SUBSYS_RPMSG:
|
||||||
|
case MM_PORT_SUBSYS_QRTR:
|
||||||
return QMI_DATA_ENDPOINT_TYPE_EMBEDDED;
|
return QMI_DATA_ENDPOINT_TYPE_EMBEDDED;
|
||||||
case MM_PORT_SUBSYS_UNKNOWN:
|
case MM_PORT_SUBSYS_UNKNOWN:
|
||||||
case MM_PORT_SUBSYS_TTY:
|
case MM_PORT_SUBSYS_TTY:
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
* Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es>
|
* Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -32,6 +33,16 @@
|
|||||||
|
|
||||||
G_DEFINE_TYPE (MMPortQmi, mm_port_qmi, MM_TYPE_PORT)
|
G_DEFINE_TYPE (MMPortQmi, mm_port_qmi, MM_TYPE_PORT)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
#if WITH_QMI
|
||||||
|
PROP_NODE,
|
||||||
|
#endif
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *properties[PROP_LAST];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
QmiService service;
|
QmiService service;
|
||||||
QmiClient *client;
|
QmiClient *client;
|
||||||
@@ -43,6 +54,10 @@ struct _MMPortQmiPrivate {
|
|||||||
QmiDevice *qmi_device;
|
QmiDevice *qmi_device;
|
||||||
GList *services;
|
GList *services;
|
||||||
gchar *net_driver;
|
gchar *net_driver;
|
||||||
|
#if defined WITH_QRTR
|
||||||
|
QrtrNode *node;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* endpoint info */
|
/* endpoint info */
|
||||||
gulong endpoint_info_signal_id;
|
gulong endpoint_info_signal_id;
|
||||||
QmiDataEndpointType endpoint_type;
|
QmiDataEndpointType endpoint_type;
|
||||||
@@ -1748,6 +1763,10 @@ internal_setup_data_format (MMPortQmi *self,
|
|||||||
ctx->wda_ul_dap_requested = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED;
|
ctx->wda_ul_dap_requested = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED;
|
||||||
ctx->wda_dl_dap_current = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED;
|
ctx->wda_dl_dap_current = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED;
|
||||||
ctx->wda_dl_dap_requested = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED;
|
ctx->wda_dl_dap_requested = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED;
|
||||||
|
|
||||||
|
if (mm_port_get_subsys (MM_PORT (self)) == MM_PORT_SUBSYS_QRTR)
|
||||||
|
ctx->use_endpoint = TRUE;
|
||||||
|
|
||||||
g_task_set_task_data (task, ctx, (GDestroyNotify) internal_setup_data_format_context_free);
|
g_task_set_task_data (task, ctx, (GDestroyNotify) internal_setup_data_format_context_free);
|
||||||
|
|
||||||
internal_setup_data_format_context_step (task);
|
internal_setup_data_format_context_step (task);
|
||||||
@@ -2155,28 +2174,36 @@ port_open_step (GTask *task)
|
|||||||
ctx->step++;
|
ctx->step++;
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
|
|
||||||
case PORT_OPEN_STEP_DEVICE_NEW: {
|
case PORT_OPEN_STEP_DEVICE_NEW:
|
||||||
GFile *file;
|
|
||||||
gchar *fullpath;
|
|
||||||
|
|
||||||
fullpath = g_strdup_printf ("/dev/%s", mm_port_get_device (MM_PORT (self)));
|
|
||||||
file = g_file_new_for_path (fullpath);
|
|
||||||
|
|
||||||
/* We flag in this point that we're opening. From now on, if we stop
|
/* We flag in this point that we're opening. From now on, if we stop
|
||||||
* for whatever reason, we should clear this flag. We do this by ensuring
|
* for whatever reason, we should clear this flag. We do this by ensuring
|
||||||
* that all callbacks go through the LAST step for completing. */
|
* that all callbacks go through the LAST step for completing. */
|
||||||
self->priv->in_progress = TRUE;
|
self->priv->in_progress = TRUE;
|
||||||
|
|
||||||
mm_obj_dbg (self, "Creating QMI device...");
|
#if defined WITH_QRTR
|
||||||
qmi_device_new (file,
|
if (self->priv->node) {
|
||||||
g_task_get_cancellable (task),
|
mm_obj_info (self, "Creating QMI device from QRTR node...");
|
||||||
(GAsyncReadyCallback) qmi_device_new_ready,
|
qmi_device_new_from_node (self->priv->node,
|
||||||
task);
|
g_task_get_cancellable (task),
|
||||||
|
(GAsyncReadyCallback) qmi_device_new_ready,
|
||||||
|
task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
g_autoptr(GFile) file = NULL;
|
||||||
|
g_autofree gchar *fullpath = NULL;
|
||||||
|
|
||||||
g_free (fullpath);
|
fullpath = g_strdup_printf ("/dev/%s", mm_port_get_device (MM_PORT (self)));
|
||||||
g_object_unref (file);
|
file = g_file_new_for_path (fullpath);
|
||||||
return;
|
|
||||||
}
|
mm_obj_dbg (self, "Creating QMI device...");
|
||||||
|
qmi_device_new (file,
|
||||||
|
g_task_get_cancellable (task),
|
||||||
|
(GAsyncReadyCallback) qmi_device_new_ready,
|
||||||
|
task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case PORT_OPEN_STEP_OPEN_WITHOUT_DATA_FORMAT:
|
case PORT_OPEN_STEP_OPEN_WITHOUT_DATA_FORMAT:
|
||||||
if (!self->priv->wda_unsupported) {
|
if (!self->priv->wda_unsupported) {
|
||||||
@@ -2451,6 +2478,20 @@ mm_port_qmi_new (const gchar *name,
|
|||||||
NULL));
|
NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined WITH_QRTR
|
||||||
|
MMPortQmi *
|
||||||
|
mm_port_qmi_new_from_node (const gchar *name,
|
||||||
|
QrtrNode *node)
|
||||||
|
{
|
||||||
|
return MM_PORT_QMI (g_object_new (MM_TYPE_PORT_QMI,
|
||||||
|
"node", node,
|
||||||
|
MM_PORT_DEVICE, name,
|
||||||
|
MM_PORT_SUBSYS, MM_PORT_SUBSYS_QRTR,
|
||||||
|
MM_PORT_TYPE, MM_PORT_TYPE_QMI,
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mm_port_qmi_init (MMPortQmi *self)
|
mm_port_qmi_init (MMPortQmi *self)
|
||||||
{
|
{
|
||||||
@@ -2463,6 +2504,51 @@ mm_port_qmi_init (MMPortQmi *self)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
#if defined WITH_QRTR
|
||||||
|
case PROP_NODE:
|
||||||
|
{
|
||||||
|
MMPortQmi *self = MM_PORT_QMI (object);
|
||||||
|
|
||||||
|
/* construct only, no new reference! */
|
||||||
|
self->priv->node = g_value_get_object (value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
#if defined WITH_QRTR
|
||||||
|
case PROP_NODE:
|
||||||
|
{
|
||||||
|
MMPortQmi *self = MM_PORT_QMI (object);
|
||||||
|
|
||||||
|
g_value_set_object (value, self->priv->node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dispose (GObject *object)
|
dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -2490,6 +2576,10 @@ dispose (GObject *object)
|
|||||||
g_clear_pointer (&self->priv->preallocated_links, g_array_unref);
|
g_clear_pointer (&self->priv->preallocated_links, g_array_unref);
|
||||||
g_clear_object (&self->priv->preallocated_links_master);
|
g_clear_object (&self->priv->preallocated_links_master);
|
||||||
|
|
||||||
|
/* Clear node object */
|
||||||
|
#if defined WITH_QRTR
|
||||||
|
g_clear_object (&self->priv->node);
|
||||||
|
#endif
|
||||||
/* Clear device object */
|
/* Clear device object */
|
||||||
g_clear_object (&self->priv->qmi_device);
|
g_clear_object (&self->priv->qmi_device);
|
||||||
|
|
||||||
@@ -2506,5 +2596,18 @@ mm_port_qmi_class_init (MMPortQmiClass *klass)
|
|||||||
g_type_class_add_private (object_class, sizeof (MMPortQmiPrivate));
|
g_type_class_add_private (object_class, sizeof (MMPortQmiPrivate));
|
||||||
|
|
||||||
/* Virtual methods */
|
/* Virtual methods */
|
||||||
|
object_class->get_property = get_property;
|
||||||
|
object_class->set_property = set_property;
|
||||||
object_class->dispose = dispose;
|
object_class->dispose = dispose;
|
||||||
|
|
||||||
|
#if defined WITH_QRTR
|
||||||
|
properties[PROP_NODE] =
|
||||||
|
g_param_spec_object ("node",
|
||||||
|
"Qrtr Node",
|
||||||
|
"Qrtr node to be probed",
|
||||||
|
QRTR_TYPE_NODE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
g_object_class_install_properties (object_class, PROP_LAST, properties);
|
||||||
}
|
}
|
||||||
|
@@ -61,6 +61,10 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMPortQmi, g_object_unref)
|
|||||||
|
|
||||||
MMPortQmi *mm_port_qmi_new (const gchar *name,
|
MMPortQmi *mm_port_qmi_new (const gchar *name,
|
||||||
MMPortSubsys subsys);
|
MMPortSubsys subsys);
|
||||||
|
#if QMI_QRTR_SUPPORTED
|
||||||
|
MMPortQmi *mm_port_qmi_new_from_node (const gchar *name,
|
||||||
|
QrtrNode *node);
|
||||||
|
#endif
|
||||||
void mm_port_qmi_open (MMPortQmi *self,
|
void mm_port_qmi_open (MMPortQmi *self,
|
||||||
gboolean set_data_format,
|
gboolean set_data_format,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
|
@@ -28,6 +28,7 @@ typedef enum { /*< underscore_name=mm_port_subsys >*/
|
|||||||
MM_PORT_SUBSYS_NET,
|
MM_PORT_SUBSYS_NET,
|
||||||
MM_PORT_SUBSYS_USBMISC,
|
MM_PORT_SUBSYS_USBMISC,
|
||||||
MM_PORT_SUBSYS_UNIX,
|
MM_PORT_SUBSYS_UNIX,
|
||||||
|
MM_PORT_SUBSYS_QRTR,
|
||||||
MM_PORT_SUBSYS_RPMSG,
|
MM_PORT_SUBSYS_RPMSG,
|
||||||
MM_PORT_SUBSYS_LAST = MM_PORT_SUBSYS_RPMSG /*< skip >*/
|
MM_PORT_SUBSYS_LAST = MM_PORT_SUBSYS_RPMSG /*< skip >*/
|
||||||
} MMPortSubsys;
|
} MMPortSubsys;
|
||||||
|
Reference in New Issue
Block a user