Compare commits
9 Commits
c3b796ef79
...
9dce5a04e6
Author | SHA1 | Date | |
---|---|---|---|
9dce5a04e6 | |||
be10ba1b8a | |||
0ece39d798 | |||
b3ace59a01 | |||
618d0dc398 | |||
ddc9b85357 | |||
177bd781d7 | |||
1a0e19908a | |||
b8aa0ae9b1 |
@ -1,17 +1,6 @@
|
||||
{ lib, config, pkgs, ... }:
|
||||
|
||||
let
|
||||
rpmsgexport = pkgs.stdenv.mkDerivation {
|
||||
name = "rpmsgexport";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
repo = "rpmsgexport";
|
||||
owner = "andersson";
|
||||
rev = "324d88d668f36c6a5e6a9c2003a050b8a5a3cd60";
|
||||
hash = "sha256-k38gj+vtEE6/s+vALzW1jiuE3HdQqaGiICdAWndu6aU=";
|
||||
};
|
||||
makeFlags = ["prefix=${placeholder "out"}"];
|
||||
};
|
||||
|
||||
saturn = pkgs.callPackage ./pkgs/saturn {};
|
||||
|
||||
drm-framebuffer = pkgs.stdenv.mkDerivation {
|
||||
@ -50,6 +39,7 @@ in {
|
||||
modemmanager-small = mm;
|
||||
satellite = prev.satellite.override { modemmanager = mm; };
|
||||
maps = final.callPackage ./pkgs/maps {};
|
||||
qmi-nmea = final.callPackage ./pkgs/qmi-nmea {};
|
||||
})
|
||||
];
|
||||
|
||||
@ -83,9 +73,7 @@ in {
|
||||
# about 10% of it). cool.
|
||||
|
||||
boot.growPartition = lib.mkForce false;
|
||||
fileSystems."/" = lib.mkDefault {
|
||||
autoResize = lib.mkForce false;
|
||||
};
|
||||
|
||||
services.udev.extraRules = ''
|
||||
ACTION!="add|change|move|bind", GOTO="mm_qcom_soc_end"
|
||||
|
||||
@ -202,6 +190,7 @@ SUBSYSTEM=="wwan", ENV{DEVNAME}=="/dev/wwan0qmi0", ENV{DEVTYPE}=="wwan_port", \
|
||||
wlr-randr
|
||||
modemmanager-small
|
||||
maps
|
||||
qmi-nmea
|
||||
];
|
||||
|
||||
users.users.dan = {
|
||||
|
@ -7,4 +7,5 @@ let
|
||||
in {
|
||||
inherit (nixos.config.system) toplevel;
|
||||
inherit (nixos.config.mobile) outputs;
|
||||
inherit (nixos) pkgs;
|
||||
}
|
||||
|
21
pkgs/qmi-nmea/Makefile
Normal file
21
pkgs/qmi-nmea/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
PREFIX?=/usr/local
|
||||
|
||||
CFLAGS=\
|
||||
-DPACKAGE_VERSION=0.1 -I. \
|
||||
$(shell $(PKG_CONFIG) --cflags qmi-glib) \
|
||||
$(shell $(PKG_CONFIG) --cflags mbim-glib) \
|
||||
$(shell $(PKG_CONFIG) --cflags glib-2.0)
|
||||
|
||||
LDFLAGS=\
|
||||
$(shell $(PKG_CONFIG) --libs qmi-glib) \
|
||||
$(shell $(PKG_CONFIG) --libs mbim-glib) \
|
||||
$(shell $(PKG_CONFIG) --libs glib-2.0)
|
||||
|
||||
default: qmi-nmea
|
||||
|
||||
SRCS=qmi-nmea.c qmicli-loc.c qmi-nmea.c
|
||||
|
||||
qmi-nmea: $(patsubst %.c,%.o,$(SRCS))
|
||||
|
||||
install:
|
||||
install -D -t $(PREFIX)/bin qmi-nmea
|
1
pkgs/qmi-nmea/config.h
Normal file
1
pkgs/qmi-nmea/config.h
Normal file
@ -0,0 +1 @@
|
||||
|
16
pkgs/qmi-nmea/default.nix
Normal file
16
pkgs/qmi-nmea/default.nix
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
stdenv,
|
||||
libqmi,
|
||||
libmbim,
|
||||
glib,
|
||||
|
||||
pkg-config
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "qmi-nmea";
|
||||
src = ./.;
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
buildInputs = [ libqmi libmbim glib ];
|
||||
PACKAGE_VERSION="1";
|
||||
makeFlags = [ "PREFIX=${placeholder "out"}" ];
|
||||
}
|
16
pkgs/qmi-nmea/qmi-common.h
Normal file
16
pkgs/qmi-nmea/qmi-common.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2023 Fabio Porcedda <fabio.porcedda@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_QMI_COMMON_H_
|
||||
#define _COMMON_QMI_COMMON_H_
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
gchar *qmi_common_str_hex (gconstpointer mem,
|
||||
gsize size,
|
||||
gchar delimiter);
|
||||
|
||||
#endif /* _COMMON_QMI_COMMON_H_ */
|
740
pkgs/qmi-nmea/qmi-nmea.c
Normal file
740
pkgs/qmi-nmea/qmi-nmea.c
Normal file
@ -0,0 +1,740 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* qmi-nmea -- enable location services and print NMEA strings
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This program started life as qmicli, which is
|
||||
*
|
||||
* Copyright (C) 2012-2023 Aleksander Morgado <aleksander@aleksander.es>
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc.
|
||||
*
|
||||
* Changes Copyright (C) 2024 Daniel Barlow
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <gio/gio.h>
|
||||
#include <glib-unix.h>
|
||||
|
||||
#include <libqmi-glib.h>
|
||||
|
||||
#if QMI_MBIM_QMUX_SUPPORTED
|
||||
#include <libmbim-glib.h>
|
||||
#endif
|
||||
|
||||
#include "qmicli.h"
|
||||
|
||||
#define PROGRAM_NAME "qmi-nmea"
|
||||
#define PROGRAM_VERSION PACKAGE_VERSION
|
||||
|
||||
/* Globals */
|
||||
static GMainLoop *loop;
|
||||
static GCancellable *cancellable;
|
||||
static QmiDevice *device;
|
||||
static QmiClient *client;
|
||||
static QmiService service;
|
||||
static gboolean operation_status;
|
||||
static gboolean expect_indications;
|
||||
#if QMI_QRTR_SUPPORTED
|
||||
static QrtrBus *qrtr_bus;
|
||||
#endif
|
||||
|
||||
/* Main options */
|
||||
static gchar *device_str;
|
||||
static gboolean get_service_version_info_flag;
|
||||
static gchar *device_set_instance_id_str;
|
||||
static gboolean device_open_version_info_flag;
|
||||
static gboolean device_open_sync_flag;
|
||||
static gchar *device_open_net_str;
|
||||
#if QMI_MBIM_QMUX_SUPPORTED
|
||||
static gboolean device_open_qmi_flag;
|
||||
static gboolean device_open_mbim_flag;
|
||||
static gboolean device_open_auto_flag;
|
||||
#endif
|
||||
static gchar *client_cid_str;
|
||||
static gboolean client_no_release_cid_flag;
|
||||
static gboolean verbose_flag;
|
||||
static gboolean verbose_full_flag;
|
||||
static gboolean silent_flag;
|
||||
static gboolean version_flag;
|
||||
|
||||
static GOptionEntry main_entries[] = {
|
||||
{ "device", 'd', 0, G_OPTION_ARG_STRING, &device_str,
|
||||
#if QMI_QRTR_SUPPORTED
|
||||
"Specify device path or QRTR URI (e.g. qrtr://0)",
|
||||
"[PATH|URI]"
|
||||
#else
|
||||
"Specify device path",
|
||||
"[PATH]"
|
||||
#endif
|
||||
},
|
||||
#if QMI_MBIM_QMUX_SUPPORTED
|
||||
{ "device-open-qmi", 0, 0, G_OPTION_ARG_NONE, &device_open_qmi_flag,
|
||||
"Open a cdc-wdm device explicitly in QMI mode",
|
||||
NULL
|
||||
},
|
||||
{ "device-open-mbim", 0, 0, G_OPTION_ARG_NONE, &device_open_mbim_flag,
|
||||
"Open a cdc-wdm device explicitly in MBIM mode",
|
||||
NULL
|
||||
},
|
||||
{ "device-open-auto", 0, 0, G_OPTION_ARG_NONE, &device_open_auto_flag,
|
||||
"Open a cdc-wdm device in either QMI or MBIM mode (default)",
|
||||
NULL
|
||||
},
|
||||
#endif
|
||||
{ "client-cid", 0, 0, G_OPTION_ARG_STRING, &client_cid_str,
|
||||
"Use the given CID, don't allocate a new one",
|
||||
"[CID]"
|
||||
},
|
||||
{ "client-no-release-cid", 0, 0, G_OPTION_ARG_NONE, &client_no_release_cid_flag,
|
||||
"Do not release the CID when exiting",
|
||||
NULL
|
||||
},
|
||||
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_flag,
|
||||
"Run action with verbose logs, including the debug ones",
|
||||
NULL
|
||||
},
|
||||
{ "verbose-full", 0, 0, G_OPTION_ARG_NONE, &verbose_full_flag,
|
||||
"Run action with verbose logs, including the debug ones and personal info",
|
||||
NULL
|
||||
},
|
||||
{ NULL, 0, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static gboolean
|
||||
signals_handler (void)
|
||||
{
|
||||
if (cancellable) {
|
||||
/* Ignore consecutive requests of cancellation */
|
||||
if (!g_cancellable_is_cancelled (cancellable)) {
|
||||
g_printerr ("cancelling the operation...\n");
|
||||
g_cancellable_cancel (cancellable);
|
||||
/* Re-set the signal handler to allow main loop cancellation on
|
||||
* second signal */
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (loop && g_main_loop_is_running (loop)) {
|
||||
g_printerr ("cancelling the main loop...\n");
|
||||
g_idle_add ((GSourceFunc) g_main_loop_quit, loop);
|
||||
}
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
const gchar *log_level_str;
|
||||
time_t now;
|
||||
gchar time_str[64];
|
||||
struct tm *local_time;
|
||||
gboolean err;
|
||||
|
||||
/* Nothing to do if we're silent */
|
||||
if (silent_flag)
|
||||
return;
|
||||
|
||||
now = time ((time_t *) NULL);
|
||||
local_time = localtime (&now);
|
||||
strftime (time_str, 64, "%d %b %Y, %H:%M:%S", local_time);
|
||||
err = FALSE;
|
||||
|
||||
switch (log_level) {
|
||||
case G_LOG_LEVEL_WARNING:
|
||||
log_level_str = "-Warning **";
|
||||
err = TRUE;
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_CRITICAL:
|
||||
case G_LOG_LEVEL_ERROR:
|
||||
log_level_str = "-Error **";
|
||||
err = TRUE;
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_DEBUG:
|
||||
log_level_str = "[Debug]";
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_MESSAGE:
|
||||
case G_LOG_LEVEL_INFO:
|
||||
log_level_str = "";
|
||||
break;
|
||||
|
||||
case G_LOG_FLAG_FATAL:
|
||||
case G_LOG_LEVEL_MASK:
|
||||
case G_LOG_FLAG_RECURSION:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (!verbose_flag && !verbose_full_flag && !err)
|
||||
return;
|
||||
|
||||
g_fprintf (err ? stderr : stdout,
|
||||
"[%s] %s %s\n",
|
||||
time_str,
|
||||
log_level_str,
|
||||
message);
|
||||
}
|
||||
|
||||
G_GNUC_NORETURN
|
||||
static void
|
||||
print_version_and_exit (void)
|
||||
{
|
||||
g_print ("qmi-nmea\n\n"
|
||||
"Copyright (C) 2012-2023 Aleksander Morgado, 2024 Daniel Barlow\n"
|
||||
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>\n"
|
||||
"This is free software: you are free to change and redistribute it.\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\n"
|
||||
"\n");
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
generic_options_enabled (void)
|
||||
{
|
||||
static guint n_actions = 0;
|
||||
static gboolean checked = FALSE;
|
||||
|
||||
if (checked)
|
||||
return !!n_actions;
|
||||
|
||||
n_actions = (!!device_set_instance_id_str +
|
||||
get_service_version_info_flag);
|
||||
|
||||
if (n_actions > 1) {
|
||||
g_printerr ("error: too many generic actions requested\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
checked = TRUE;
|
||||
return !!n_actions;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Report that indications are expected */
|
||||
|
||||
void
|
||||
qmicli_expect_indications (void)
|
||||
{
|
||||
expect_indications = TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Running asynchronously */
|
||||
|
||||
static void
|
||||
close_ready (QmiDevice *dev,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!qmi_device_close_finish (dev, res, &error)) {
|
||||
g_printerr ("error: couldn't close: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
} else
|
||||
g_debug ("Closed");
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
release_client_ready (QmiDevice *dev,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!qmi_device_release_client_finish (dev, res, &error)) {
|
||||
g_printerr ("error: couldn't release client: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
} else
|
||||
g_debug ("Client released");
|
||||
|
||||
qmi_device_close_async (dev, 10, NULL, (GAsyncReadyCallback) close_ready, NULL);
|
||||
}
|
||||
|
||||
static guint8 saved_cid = QMI_CID_NONE;
|
||||
|
||||
void
|
||||
qmicli_async_operation_done (gboolean reported_operation_status,
|
||||
gboolean skip_cid_release)
|
||||
{
|
||||
QmiDeviceReleaseClientFlags flags = QMI_DEVICE_RELEASE_CLIENT_FLAGS_NONE;
|
||||
|
||||
/* Keep the result of the operation */
|
||||
operation_status = reported_operation_status;
|
||||
|
||||
/* Cleanup cancellation */
|
||||
g_clear_object (&cancellable);
|
||||
|
||||
/* If no client was allocated (e.g. generic action), just quit */
|
||||
if (!client) {
|
||||
g_main_loop_quit (loop);
|
||||
return;
|
||||
}
|
||||
|
||||
if (skip_cid_release) {
|
||||
g_debug ("Skipped CID release");
|
||||
saved_cid = qmi_client_get_cid (client);
|
||||
}
|
||||
else if (!client_no_release_cid_flag)
|
||||
flags |= QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID;
|
||||
else
|
||||
g_print ("[%s] Client ID not released:\n"
|
||||
"\tService: '%s'\n"
|
||||
"\t CID: '%u'\n",
|
||||
qmi_device_get_path_display (device),
|
||||
qmi_service_get_string (service),
|
||||
qmi_client_get_cid (client));
|
||||
|
||||
qmi_device_release_client (device,
|
||||
client,
|
||||
flags,
|
||||
10,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)release_client_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
allocate_client_ready (QmiDevice *dev,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
client = qmi_device_allocate_client_finish (dev, res, &error);
|
||||
if (!client) {
|
||||
g_printerr ("error: couldn't create client for the '%s' service: %s\n",
|
||||
qmi_service_get_string (service),
|
||||
error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Run the service-specific action */
|
||||
switch (service) {
|
||||
case QMI_SERVICE_LOC:
|
||||
#if defined HAVE_QMI_SERVICE_LOC
|
||||
qmicli_loc_run (dev, QMI_CLIENT_LOC (client), cancellable);
|
||||
return;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
device_allocate_client (QmiDevice *dev)
|
||||
{
|
||||
guint8 cid = QMI_CID_NONE;
|
||||
|
||||
if (client_cid_str) {
|
||||
guint32 cid32;
|
||||
|
||||
cid32 = atoi (client_cid_str);
|
||||
if (!cid32 || cid32 > G_MAXUINT8) {
|
||||
g_printerr ("error: invalid CID given '%s'\n",
|
||||
client_cid_str);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cid = (guint8)cid32;
|
||||
g_debug ("Reusing CID '%u'", cid);
|
||||
}
|
||||
if (saved_cid != QMI_CID_NONE) {
|
||||
cid = saved_cid;
|
||||
g_debug ("Using saved CID '%u'", cid);
|
||||
}
|
||||
|
||||
/* As soon as we get the QmiDevice, create a client for the requested
|
||||
* service */
|
||||
qmi_device_allocate_client (dev,
|
||||
service,
|
||||
cid,
|
||||
10,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)allocate_client_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
set_instance_id_ready (QmiDevice *dev,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
GError *error = NULL;
|
||||
guint16 link_id;
|
||||
|
||||
if (!qmi_device_set_instance_id_finish (dev, res, &link_id, &error)) {
|
||||
g_printerr ("error: couldn't set instance ID: %s\n",
|
||||
error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_print ("[%s] Instance ID set:\n"
|
||||
"\tLink ID: '%" G_GUINT16_FORMAT "'\n",
|
||||
qmi_device_get_path_display (dev),
|
||||
link_id);
|
||||
|
||||
/* We're done now */
|
||||
qmicli_async_operation_done (TRUE, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
device_set_instance_id (QmiDevice *dev)
|
||||
{
|
||||
gint instance_id;
|
||||
|
||||
if (g_str_equal (device_set_instance_id_str, "0"))
|
||||
instance_id = 0;
|
||||
else {
|
||||
instance_id = atoi (device_set_instance_id_str);
|
||||
if (instance_id == 0) {
|
||||
g_printerr ("error: invalid instance ID given: '%s'\n", device_set_instance_id_str);
|
||||
exit (EXIT_FAILURE);
|
||||
} else if (instance_id < 0 || instance_id > G_MAXUINT8) {
|
||||
g_printerr ("error: given instance ID is out of range [0,%u]: '%s'\n",
|
||||
G_MAXUINT8,
|
||||
device_set_instance_id_str);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
g_debug ("Setting instance ID '%d'...", instance_id);
|
||||
qmi_device_set_instance_id (dev,
|
||||
(guint8)instance_id,
|
||||
10,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)set_instance_id_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
get_service_version_info_ready (QmiDevice *dev,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GArray *services;
|
||||
guint i;
|
||||
|
||||
services = qmi_device_get_service_version_info_finish (dev, res, &error);
|
||||
if (!services) {
|
||||
g_printerr ("error: couldn't get service version info: %s\n",
|
||||
error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_print ("[%s] Supported versions:\n",
|
||||
qmi_device_get_path_display (dev));
|
||||
for (i = 0; i < services->len; i++) {
|
||||
QmiDeviceServiceVersionInfo *info;
|
||||
const gchar *service_str;
|
||||
|
||||
info = &g_array_index (services, QmiDeviceServiceVersionInfo, i);
|
||||
service_str = qmi_service_get_string (info->service);
|
||||
if (service_str)
|
||||
g_print ("\t%s (%u.%u)\n",
|
||||
service_str,
|
||||
info->major_version,
|
||||
info->minor_version);
|
||||
else
|
||||
g_print ("\tunknown [0x%02x] (%u.%u)\n",
|
||||
info->service,
|
||||
info->major_version,
|
||||
info->minor_version);
|
||||
}
|
||||
g_array_unref (services);
|
||||
|
||||
/* We're done now */
|
||||
qmicli_async_operation_done (TRUE, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
device_get_service_version_info (QmiDevice *dev)
|
||||
{
|
||||
g_debug ("Getting service version info...");
|
||||
qmi_device_get_service_version_info (dev,
|
||||
10,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)get_service_version_info_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
device_open_ready (QmiDevice *dev,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!qmi_device_open_finish (dev, res, &error)) {
|
||||
g_printerr ("error: couldn't open the QmiDevice: %s\n",
|
||||
error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_debug ("QMI Device at '%s' ready",
|
||||
qmi_device_get_path_display (dev));
|
||||
|
||||
if (device_set_instance_id_str)
|
||||
device_set_instance_id (dev);
|
||||
else if (get_service_version_info_flag)
|
||||
device_get_service_version_info (dev);
|
||||
else
|
||||
device_allocate_client (dev);
|
||||
}
|
||||
|
||||
static void
|
||||
device_new_ready (GObject *unused,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
QmiDeviceOpenFlags open_flags = QMI_DEVICE_OPEN_FLAGS_NONE;
|
||||
GError *error = NULL;
|
||||
|
||||
device = qmi_device_new_finish (res, &error);
|
||||
if (!device) {
|
||||
g_printerr ("error: couldn't create QmiDevice: %s\n",
|
||||
error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#if QMI_MBIM_QMUX_SUPPORTED
|
||||
if (device_open_mbim_flag + device_open_qmi_flag + device_open_auto_flag > 1) {
|
||||
g_printerr ("error: cannot specify multiple mode flags to open device\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup device open flags */
|
||||
if (device_open_version_info_flag)
|
||||
open_flags |= QMI_DEVICE_OPEN_FLAGS_VERSION_INFO;
|
||||
if (device_open_sync_flag)
|
||||
open_flags |= QMI_DEVICE_OPEN_FLAGS_SYNC;
|
||||
open_flags |= QMI_DEVICE_OPEN_FLAGS_PROXY;
|
||||
#if QMI_MBIM_QMUX_SUPPORTED
|
||||
if (device_open_mbim_flag)
|
||||
open_flags |= QMI_DEVICE_OPEN_FLAGS_MBIM;
|
||||
if (device_open_auto_flag || (!device_open_qmi_flag && !device_open_mbim_flag))
|
||||
open_flags |= QMI_DEVICE_OPEN_FLAGS_AUTO;
|
||||
#endif
|
||||
if (expect_indications)
|
||||
open_flags |= QMI_DEVICE_OPEN_FLAGS_EXPECT_INDICATIONS;
|
||||
if (device_open_net_str) {
|
||||
if (!qmicli_read_device_open_flags_from_string (device_open_net_str, &open_flags) ||
|
||||
!qmicli_validate_device_open_flags (open_flags))
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Open the device */
|
||||
qmi_device_open (device,
|
||||
open_flags,
|
||||
15,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)device_open_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#if QMI_QRTR_SUPPORTED
|
||||
|
||||
static void
|
||||
bus_new_ready (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
guint node_id;
|
||||
QrtrNode *node;
|
||||
|
||||
node_id = GPOINTER_TO_UINT (user_data);
|
||||
|
||||
qrtr_bus = qrtr_bus_new_finish (res, &error);
|
||||
if (!qrtr_bus) {
|
||||
g_printerr ("error: couldn't access QRTR bus: %s\n", error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
node = qrtr_bus_peek_node (qrtr_bus, node_id);
|
||||
if (!node) {
|
||||
g_printerr ("error: node with id %u not found in QRTR bus\n", node_id);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
qmi_device_new_from_node (node,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)device_new_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
make_device (GFile *file)
|
||||
{
|
||||
g_autofree gchar *id = NULL;
|
||||
|
||||
id = g_file_get_path (file);
|
||||
if (id) {
|
||||
/* Describes a local device file. */
|
||||
qmi_device_new (file,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)device_new_ready,
|
||||
NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if QMI_QRTR_SUPPORTED
|
||||
{
|
||||
guint32 node_id;
|
||||
|
||||
id = g_file_get_uri (file);
|
||||
if (qrtr_get_node_for_uri (id, &node_id)) {
|
||||
qrtr_bus_new (1000, /* ms */
|
||||
cancellable,
|
||||
(GAsyncReadyCallback)bus_new_ready,
|
||||
GUINT_TO_POINTER (node_id));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_printerr ("error: URI is neither a local file path nor a QRTR node: %s\n", id);
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
g_printerr ("error: URI is not a local file path: %s\n", id);
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
parse_actions (void)
|
||||
{
|
||||
guint actions_enabled = 0;
|
||||
|
||||
qmicli_loc_options_enabled ();
|
||||
service = QMI_SERVICE_LOC;
|
||||
|
||||
/* Go on! */
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GFile *file;
|
||||
GOptionContext *context;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
/* Setup option context, process it and destroy it */
|
||||
context = g_option_context_new ("- Control QMI devices");
|
||||
#if defined HAVE_QMI_SERVICE_LOC
|
||||
g_option_context_add_group (context, qmicli_loc_get_option_group ());
|
||||
#endif
|
||||
g_option_context_add_main_entries (context, main_entries, NULL);
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error)) {
|
||||
g_printerr ("error: %s\n",
|
||||
error->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
g_option_context_free (context);
|
||||
|
||||
if (version_flag)
|
||||
print_version_and_exit ();
|
||||
|
||||
g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, NULL);
|
||||
g_log_set_handler ("Qmi", G_LOG_LEVEL_MASK, log_handler, NULL);
|
||||
|
||||
if (verbose_flag && verbose_full_flag) {
|
||||
g_printerr ("error: cannot specify --verbose and --verbose-full at the same time\n");
|
||||
exit (EXIT_FAILURE);
|
||||
} else if (verbose_flag) {
|
||||
qmi_utils_set_traces_enabled (TRUE);
|
||||
qmi_utils_set_show_personal_info (FALSE);
|
||||
} else if (verbose_full_flag) {
|
||||
qmi_utils_set_traces_enabled (TRUE);
|
||||
qmi_utils_set_show_personal_info (TRUE);
|
||||
}
|
||||
|
||||
#if QMI_MBIM_QMUX_SUPPORTED
|
||||
/* libmbim logging */
|
||||
g_log_set_handler ("Mbim", G_LOG_LEVEL_MASK, log_handler, NULL);
|
||||
if (verbose_flag) {
|
||||
mbim_utils_set_traces_enabled (TRUE);
|
||||
#if MBIM_CHECK_VERSION(1,27,6)
|
||||
mbim_utils_set_show_personal_info (FALSE);
|
||||
#endif
|
||||
} else if (verbose_full_flag) {
|
||||
mbim_utils_set_traces_enabled (TRUE);
|
||||
#if MBIM_CHECK_VERSION(1,27,6)
|
||||
mbim_utils_set_show_personal_info (TRUE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if QMI_QRTR_SUPPORTED
|
||||
/* libqrtr-glib logging */
|
||||
g_log_set_handler ("Qrtr", G_LOG_LEVEL_MASK, log_handler, NULL);
|
||||
#endif
|
||||
|
||||
/* No device path given? */
|
||||
if (!device_str) {
|
||||
g_printerr ("error: no device path specified\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Build new GFile from the commandline arg */
|
||||
file = g_file_new_for_commandline_arg (device_str);
|
||||
|
||||
parse_actions ();
|
||||
|
||||
for(int i=0; i<2; i++){
|
||||
/* Create requirements for async options */
|
||||
cancellable = g_cancellable_new ();
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/* Setup signals */
|
||||
g_unix_signal_add (SIGINT, (GSourceFunc) signals_handler, NULL);
|
||||
g_unix_signal_add (SIGHUP, (GSourceFunc) signals_handler, NULL);
|
||||
g_unix_signal_add (SIGTERM, (GSourceFunc) signals_handler, NULL);
|
||||
|
||||
/* Launch QmiDevice creation */
|
||||
if (!make_device (file))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
g_main_loop_run (loop);
|
||||
if (cancellable)
|
||||
g_object_unref (cancellable);
|
||||
if (client)
|
||||
g_object_unref (client);
|
||||
if (device)
|
||||
g_object_unref (device);
|
||||
g_main_loop_unref (loop);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
|
||||
return (operation_status ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
155
pkgs/qmi-nmea/qmicli
Normal file
155
pkgs/qmi-nmea/qmicli
Normal file
@ -0,0 +1,155 @@
|
||||
# qmicli(1) completion -*- shell-script -*-
|
||||
|
||||
_qmicli()
|
||||
{
|
||||
local cur prev words cword split
|
||||
_init_completion -s || return
|
||||
|
||||
case $prev in
|
||||
-d|--device)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
'--device-set-instance-id')
|
||||
COMPREPLY=( $(compgen -W "[Instance-ID]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--device-open-net')
|
||||
COMPREPLY=( $(compgen -W "[net-802-3|net-raw-ip|net-qos-header|net-no-qos-header]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--client-cid')
|
||||
COMPREPLY=( $(compgen -W "[CID]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-uim-set-pin-protection')
|
||||
COMPREPLY=( $(compgen -W "[(PIN|PIN2),(disable|enable),(current-PIN)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-uim-verify-pin')
|
||||
COMPREPLY=( $(compgen -W "[(PIN|PIN2),(current-PIN)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-uim-unblock-pin')
|
||||
COMPREPLY=( $(compgen -W "[(PIN|PIN2),(PUK),(new-PIN)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-uim-change-pin')
|
||||
COMPREPLY=( $(compgen -W "[(PIN|PIN2),(old-PIN),(new-PIN)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-uim-get-ck-status')
|
||||
COMPREPLY=( $(compgen -W "[(pn|pu|pp|pc|pf)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-uim-set-ck-protection')
|
||||
COMPREPLY=( $(compgen -W "[(pn|pu|pp|pc|pf),(disable),(key)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-uim-unblock-ck')
|
||||
COMPREPLY=( $(compgen -W "[(pn|pu|pp|pc|pf),(key)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-set-operating-mode')
|
||||
COMPREPLY=( $(compgen -W "[(Operating-Mode)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-activate-automatic')
|
||||
COMPREPLY=( $(compgen -W "[Activation-Code]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-activate-manual')
|
||||
COMPREPLY=( $(compgen -W "[SPC,SID,MDN,MIN]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-set-user-lock-state')
|
||||
COMPREPLY=( $(compgen -W "[(disable|enable),(current-lock-code)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-set-user-lock-code')
|
||||
COMPREPLY=( $(compgen -W "[(old-lock-code),(new-lock-code)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-write-user-data')
|
||||
COMPREPLY=( $(compgen -W "[(User-data)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-restore-factory-defaults')
|
||||
COMPREPLY=( $(compgen -W "[(Service-Programming-Code)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-validate-service-programming-code')
|
||||
COMPREPLY=( $(compgen -W "[(Service-Programming-Code)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-select-stored-image')
|
||||
COMPREPLY=( $(compgen -W "[modem#,pri#]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--dms-delete-stored-image')
|
||||
COMPREPLY=( $(compgen -W "[modem#,pri#]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--nas-get-tx-rx-info')
|
||||
COMPREPLY=( $(compgen -W "[(Radio-Interface)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--nas-set-system-selection-preference')
|
||||
COMPREPLY=( $(compgen -W "[cdma-1x|cdma-1xevdo|gsm|umts|lte|td-scdma]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--wds-start-network')
|
||||
COMPREPLY=( $(compgen -W "[(APN),(PAP|CHAP|BOTH),(Username),(Password)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--wds-stop-network')
|
||||
COMPREPLY=( $(compgen -W "[Packet-data-handle]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--wds-get-profile-list')
|
||||
COMPREPLY=( $(compgen -W "[3gpp|3gpp2]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--wds-get-default-settings')
|
||||
COMPREPLY=( $(compgen -W "[3gpp|3gpp2]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--wds-bind-mux-data-port')
|
||||
COMPREPLY=( $(compgen -W "[(MuxId),(Ep-Iface-Number)]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--wds-set-ip-family')
|
||||
COMPREPLY=( $(compgen -W "[4|6]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--uim-read-transparent')
|
||||
COMPREPLY=( $(compgen -W "[0xNNNN,0xNNNN,...]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--uim-get-file-attributes')
|
||||
COMPREPLY=( $(compgen -W "[0xNNNN,0xNNNN,...]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'--wda-set-data-format')
|
||||
COMPREPLY=( $(compgen -W "[raw-ip|802-3]" -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
'-V'|'--version')
|
||||
return 0
|
||||
;;
|
||||
'-h'|'--help'|'--help-all'|'--help-dms'|'--help-nas'|'--help-wds'|'--help-pbm'|'--help-uim'|'--help-wda')
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
$split && return 0
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $( compgen -W '$( _parse_help "$1" --help-all )' -- "$cur" ) )
|
||||
[[ $COMPREPLY == *= ]] && compopt -o nospace
|
||||
return 0
|
||||
fi
|
||||
} &&
|
||||
complete -F _qmicli qmicli
|
||||
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
441
pkgs/qmi-nmea/qmicli-loc.c
Normal file
441
pkgs/qmi-nmea/qmicli-loc.c
Normal file
@ -0,0 +1,441 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* qmicli -- Command line interface to control QMI devices
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (C) 2018 Thomas Weißschuh <thomas@weissschuh.net>
|
||||
* Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <libqmi-glib.h>
|
||||
|
||||
#include "qmicli.h"
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_LOC
|
||||
|
||||
#undef VALIDATE_MASK_NONE
|
||||
#define VALIDATE_MASK_NONE(str) (str ? str : "none")
|
||||
|
||||
/* Context */
|
||||
|
||||
typedef enum {
|
||||
MONITORING_STEP_FIRST,
|
||||
MONITORING_STEP_REGISTER_EVENTS,
|
||||
MONITORING_STEP_SETUP_TIMEOUT,
|
||||
MONITORING_STEP_ONGOING,
|
||||
} MonitoringStep;
|
||||
|
||||
typedef struct {
|
||||
QmiDevice *device;
|
||||
QmiClientLoc *client;
|
||||
GCancellable *cancellable;
|
||||
guint timeout_id;
|
||||
MonitoringStep monitoring_step;
|
||||
guint nmea_indication_id;
|
||||
} Context;
|
||||
static Context *ctx;
|
||||
|
||||
/* Options */
|
||||
static gint session_id;
|
||||
static gboolean start_flag = 1;
|
||||
static gboolean stop_flag;
|
||||
static gint timeout;
|
||||
static gboolean follow_nmea_flag;
|
||||
static gboolean noop_flag;
|
||||
|
||||
#define DEFAULT_LOC_TIMEOUT_SECS 30
|
||||
|
||||
static GOptionEntry entries[] = {
|
||||
{ NULL, 0, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
GOptionGroup *
|
||||
qmicli_loc_get_option_group (void)
|
||||
{
|
||||
GOptionGroup *group;
|
||||
|
||||
group = g_option_group_new ("loc",
|
||||
"LOC options:",
|
||||
"Show location options", NULL, NULL);
|
||||
g_option_group_add_entries (group, entries);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
gboolean
|
||||
qmicli_loc_options_enabled (void)
|
||||
{
|
||||
start_flag = !0;
|
||||
follow_nmea_flag = 0;
|
||||
g_debug("enabled %u %u", start_flag, follow_nmea_flag);
|
||||
return start_flag;
|
||||
}
|
||||
|
||||
static void
|
||||
context_free (Context *context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
if (context->timeout_id)
|
||||
g_source_remove (context->timeout_id);
|
||||
|
||||
if (context->nmea_indication_id)
|
||||
g_signal_handler_disconnect (context->client, context->nmea_indication_id);
|
||||
|
||||
g_clear_object (&context->cancellable);
|
||||
g_clear_object (&context->client);
|
||||
g_clear_object (&context->device);
|
||||
g_slice_free (Context, context);
|
||||
}
|
||||
|
||||
static void
|
||||
operation_shutdown (gboolean operation_status)
|
||||
{
|
||||
context_free (ctx);
|
||||
qmicli_async_operation_done (operation_status, FALSE);
|
||||
}
|
||||
|
||||
#if (defined HAVE_QMI_INDICATION_LOC_POSITION_REPORT || \
|
||||
defined HAVE_QMI_INDICATION_LOC_GNSS_SV_INFO || \
|
||||
defined HAVE_QMI_INDICATION_LOC_NMEA) && \
|
||||
defined HAVE_QMI_MESSAGE_LOC_REGISTER_EVENTS
|
||||
|
||||
static void monitoring_step_run (void);
|
||||
|
||||
static gboolean
|
||||
monitoring_timed_out (void)
|
||||
{
|
||||
ctx->timeout_id = 0;
|
||||
g_printerr ("error: operation failed: timeout\n");
|
||||
operation_shutdown (FALSE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
monitoring_cancelled (GCancellable *cancellable)
|
||||
{
|
||||
/* For FOLLOW operations, silently exit */
|
||||
if (follow_nmea_flag) {
|
||||
operation_shutdown (TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
#endif /* HAVE_QMI_INDICATION_LOC_POSITION_REPORT
|
||||
* HAVE_QMI_INDICATION_LOC_GNSS_SV_INFO
|
||||
* HAVE_QMI_INDICATION_LOC_NMEA */
|
||||
|
||||
#if defined HAVE_QMI_INDICATION_LOC_NMEA && defined HAVE_QMI_MESSAGE_LOC_REGISTER_EVENTS
|
||||
|
||||
static void
|
||||
nmea_received (QmiClientLoc *client,
|
||||
QmiIndicationLocNmeaOutput *output)
|
||||
{
|
||||
const gchar *nmea = NULL;
|
||||
|
||||
qmi_indication_loc_nmea_output_get_nmea_string (output, &nmea, NULL);
|
||||
if (nmea)
|
||||
/* Note: NMEA traces already have an EOL */
|
||||
g_print ("%s", nmea);
|
||||
}
|
||||
|
||||
#endif /* HAVE_QMI_INDICATION_LOC_NMEA */
|
||||
|
||||
|
||||
#if (defined HAVE_QMI_INDICATION_LOC_POSITION_REPORT || \
|
||||
defined HAVE_QMI_INDICATION_LOC_GNSS_SV_INFO || \
|
||||
defined HAVE_QMI_INDICATION_LOC_NMEA) && \
|
||||
defined HAVE_QMI_MESSAGE_LOC_REGISTER_EVENTS
|
||||
|
||||
static void
|
||||
monitoring_step_ongoing (void)
|
||||
{
|
||||
#if defined HAVE_QMI_INDICATION_LOC_NMEA
|
||||
if (follow_nmea_flag)
|
||||
ctx->nmea_indication_id = g_signal_connect (ctx->client,
|
||||
"nmea",
|
||||
G_CALLBACK (nmea_received),
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
g_assert (ctx->nmea_indication_id);
|
||||
}
|
||||
|
||||
static void
|
||||
monitoring_step_setup_timeout (void)
|
||||
{
|
||||
/* User can use Ctrl+C to cancel the monitoring at any time */
|
||||
g_cancellable_connect (ctx->cancellable,
|
||||
G_CALLBACK (monitoring_cancelled),
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
|
||||
/* Go on */
|
||||
ctx->monitoring_step++;
|
||||
monitoring_step_run ();
|
||||
}
|
||||
|
||||
static void
|
||||
register_events_ready (QmiClientLoc *client,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
QmiMessageLocRegisterEventsOutput *output;
|
||||
GError *error = NULL;
|
||||
|
||||
output = qmi_client_loc_register_events_finish (client, res, &error);
|
||||
if (!output) {
|
||||
g_printerr ("error: operation failed: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
operation_shutdown (FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!qmi_message_loc_register_events_output_get_result (output, &error)) {
|
||||
g_printerr ("error: could not register location tracking events: %s\n", error->message);
|
||||
qmi_message_loc_register_events_output_unref (output);
|
||||
g_error_free (error);
|
||||
operation_shutdown (FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("Registered location tracking events...");
|
||||
|
||||
/* Go on */
|
||||
ctx->monitoring_step++;
|
||||
monitoring_step_run ();
|
||||
|
||||
qmi_message_loc_register_events_output_unref (output);
|
||||
}
|
||||
|
||||
static void
|
||||
monitoring_step_register_events (void)
|
||||
{
|
||||
QmiMessageLocRegisterEventsInput *re_input;
|
||||
QmiLocEventRegistrationFlag indication_mask = 0;
|
||||
|
||||
/* Configure events to enable */
|
||||
|
||||
if (follow_nmea_flag)
|
||||
indication_mask |= QMI_LOC_EVENT_REGISTRATION_FLAG_NMEA;
|
||||
|
||||
g_assert (indication_mask);
|
||||
|
||||
re_input = qmi_message_loc_register_events_input_new ();
|
||||
qmi_message_loc_register_events_input_set_event_registration_mask (
|
||||
re_input, indication_mask, NULL);
|
||||
qmi_client_loc_register_events (ctx->client,
|
||||
re_input,
|
||||
10,
|
||||
ctx->cancellable,
|
||||
(GAsyncReadyCallback) register_events_ready,
|
||||
NULL);
|
||||
qmi_message_loc_register_events_input_unref (re_input);
|
||||
}
|
||||
|
||||
static void
|
||||
monitoring_step_run (void)
|
||||
{
|
||||
switch (ctx->monitoring_step) {
|
||||
case MONITORING_STEP_FIRST:
|
||||
ctx->monitoring_step++;
|
||||
/* fall through */
|
||||
|
||||
case MONITORING_STEP_REGISTER_EVENTS:
|
||||
monitoring_step_register_events ();
|
||||
return;
|
||||
|
||||
case MONITORING_STEP_SETUP_TIMEOUT:
|
||||
monitoring_step_setup_timeout ();
|
||||
return;
|
||||
|
||||
case MONITORING_STEP_ONGOING:
|
||||
monitoring_step_ongoing ();
|
||||
return;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_QMI_INDICATION_LOC_POSITION_REPORT
|
||||
* HAVE_QMI_INDICATION_LOC_GNSS_SV_INFO
|
||||
* HAVE_QMI_INDICATION_LOC_NMEA */
|
||||
|
||||
|
||||
#if defined HAVE_QMI_MESSAGE_LOC_STOP
|
||||
|
||||
static void
|
||||
stop_ready (QmiClientLoc *client,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
QmiMessageLocStopOutput *output;
|
||||
GError *error = NULL;
|
||||
|
||||
output = qmi_client_loc_stop_finish (client, res, &error);
|
||||
if (!output) {
|
||||
g_printerr ("error: operation failed: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
operation_shutdown (FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!qmi_message_loc_stop_output_get_result (output, &error)) {
|
||||
g_printerr ("error: could not stop location tracking: %s\n", error->message);
|
||||
qmi_message_loc_stop_output_unref (output);
|
||||
g_error_free (error);
|
||||
operation_shutdown (FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
g_print ("[%s] Successfully stopped location tracking (session id %u)\n",
|
||||
qmi_device_get_path_display (ctx->device), session_id);
|
||||
|
||||
qmi_message_loc_stop_output_unref (output);
|
||||
operation_shutdown (TRUE);
|
||||
}
|
||||
|
||||
#endif /* HAVE_QMI_MESSAGE_LOC_STOP */
|
||||
|
||||
#if defined HAVE_QMI_MESSAGE_LOC_START
|
||||
|
||||
static void
|
||||
start_ready (QmiClientLoc *client,
|
||||
GAsyncResult *res)
|
||||
{
|
||||
QmiMessageLocStartOutput *output;
|
||||
GError *error = NULL;
|
||||
|
||||
output = qmi_client_loc_start_finish (client, res, &error);
|
||||
if (!output) {
|
||||
g_printerr ("error: operation failed: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
operation_shutdown (FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!qmi_message_loc_start_output_get_result (output, &error)) {
|
||||
g_printerr ("error: could not start location tracking: %s\n", error->message);
|
||||
qmi_message_loc_start_output_unref (output);
|
||||
g_error_free (error);
|
||||
operation_shutdown (FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
g_print ("[%s] Successfully started location tracking (session id %u)\n",
|
||||
qmi_device_get_path_display (ctx->device), session_id);
|
||||
|
||||
qmi_message_loc_start_output_unref (output);
|
||||
context_free (ctx);
|
||||
qmicli_async_operation_done (TRUE, TRUE);
|
||||
}
|
||||
|
||||
#endif /* HAVE_QMI_MESSAGE_LOC_START */
|
||||
|
||||
static gboolean
|
||||
noop_cb (gpointer unused)
|
||||
{
|
||||
operation_shutdown (TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
qmicli_loc_run (QmiDevice *device,
|
||||
QmiClientLoc *client,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
/* Initialize context */
|
||||
ctx = g_slice_new0 (Context);
|
||||
ctx->device = g_object_ref (device);
|
||||
ctx->client = g_object_ref (client);
|
||||
ctx->cancellable = g_object_ref (cancellable);
|
||||
|
||||
g_debug("qmicli_loc_run start_flag %u stop-flag %u follow_nmea_flag %u",
|
||||
start_flag, stop_flag, follow_nmea_flag);
|
||||
|
||||
#if defined HAVE_QMI_MESSAGE_LOC_START
|
||||
if (start_flag) {
|
||||
QmiMessageLocStartInput *input;
|
||||
|
||||
input = qmi_message_loc_start_input_new ();
|
||||
qmi_message_loc_start_input_set_session_id (input, (guint8) session_id, NULL);
|
||||
qmi_message_loc_start_input_set_intermediate_report_state (input, QMI_LOC_INTERMEDIATE_REPORT_STATE_ENABLE, NULL);
|
||||
qmi_message_loc_start_input_set_minimum_interval_between_position_reports (input, 1000, NULL);
|
||||
qmi_message_loc_start_input_set_fix_recurrence_type (input, QMI_LOC_FIX_RECURRENCE_TYPE_REQUEST_PERIODIC_FIXES, NULL);
|
||||
qmi_client_loc_start (ctx->client,
|
||||
input,
|
||||
10,
|
||||
ctx->cancellable,
|
||||
(GAsyncReadyCallback) start_ready,
|
||||
NULL);
|
||||
qmi_message_loc_start_input_unref (input);
|
||||
start_flag = 0;
|
||||
follow_nmea_flag = 1;
|
||||
g_debug("qmicli_loc_run returning, start_flag %u stop-flag %u follow_nmea_flag %u",
|
||||
start_flag, stop_flag, follow_nmea_flag);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_MESSAGE_LOC_STOP
|
||||
if (stop_flag) {
|
||||
QmiMessageLocStopInput *input;
|
||||
|
||||
input = qmi_message_loc_stop_input_new ();
|
||||
qmi_message_loc_stop_input_set_session_id (input, (guint8) session_id, NULL);
|
||||
qmi_client_loc_stop (ctx->client,
|
||||
input,
|
||||
10,
|
||||
ctx->cancellable,
|
||||
(GAsyncReadyCallback) stop_ready,
|
||||
NULL);
|
||||
qmi_message_loc_stop_input_unref (input);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (follow_nmea_flag) {
|
||||
qmicli_expect_indications ();
|
||||
/* All the remaining actions require monitoring */
|
||||
ctx->monitoring_step = MONITORING_STEP_FIRST;
|
||||
monitoring_step_run ();
|
||||
g_debug("qmicli_loc_run returning, start_flag %u stop-flag %u follow_nmea_flag %u",
|
||||
start_flag, stop_flag, follow_nmea_flag);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Just client allocate/release? */
|
||||
if (noop_flag) {
|
||||
g_idle_add (noop_cb, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
||||
#endif /* HAVE_QMI_SERVICE_LOC */
|
212
pkgs/qmi-nmea/qmicli.h
Normal file
212
pkgs/qmi-nmea/qmicli.h
Normal file
@ -0,0 +1,212 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* qmicli -- Command line interface to control QMI devices
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <libqmi-glib.h>
|
||||
|
||||
#ifndef __QMICLI_H__
|
||||
#define __QMICLI_H__
|
||||
|
||||
/* Common */
|
||||
void qmicli_async_operation_done (gboolean reported_operation_status,
|
||||
gboolean skip_cid_release);
|
||||
void qmicli_expect_indications (void);
|
||||
|
||||
/* qmi_wwan specific */
|
||||
GOptionGroup *qmicli_qmiwwan_get_option_group (void);
|
||||
gboolean qmicli_qmiwwan_options_enabled (void);
|
||||
void qmicli_qmiwwan_run (QmiDevice *device,
|
||||
GCancellable *cancellable);
|
||||
|
||||
/* link management */
|
||||
GOptionGroup *qmicli_link_management_get_option_group (void);
|
||||
gboolean qmicli_link_management_options_enabled (void);
|
||||
void qmicli_link_management_run (QmiDevice *device,
|
||||
GCancellable *cancellable);
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_DMS
|
||||
GOptionGroup *qmicli_dms_get_option_group (void);
|
||||
gboolean qmicli_dms_options_enabled (void);
|
||||
void qmicli_dms_run (QmiDevice *device,
|
||||
QmiClientDms *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_WDS
|
||||
GOptionGroup *qmicli_wds_get_option_group (void);
|
||||
gboolean qmicli_wds_options_enabled (void);
|
||||
void qmicli_wds_run (QmiDevice *device,
|
||||
QmiClientWds *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_NAS
|
||||
GOptionGroup *qmicli_nas_get_option_group (void);
|
||||
gboolean qmicli_nas_options_enabled (void);
|
||||
void qmicli_nas_run (QmiDevice *device,
|
||||
QmiClientNas *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_PBM
|
||||
GOptionGroup *qmicli_pbm_get_option_group (void);
|
||||
gboolean qmicli_pbm_options_enabled (void);
|
||||
void qmicli_pbm_run (QmiDevice *device,
|
||||
QmiClientPbm *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_PDC
|
||||
GOptionGroup *qmicli_pdc_get_option_group (void);
|
||||
gboolean qmicli_pdc_options_enabled (void);
|
||||
void qmicli_pdc_run (QmiDevice *device,
|
||||
QmiClientPdc *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_UIM
|
||||
GOptionGroup *qmicli_uim_get_option_group (void);
|
||||
gboolean qmicli_uim_options_enabled (void);
|
||||
void qmicli_uim_run (QmiDevice *device,
|
||||
QmiClientUim *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_WMS
|
||||
GOptionGroup *qmicli_wms_get_option_group (void);
|
||||
gboolean qmicli_wms_options_enabled (void);
|
||||
void qmicli_wms_run (QmiDevice *device,
|
||||
QmiClientWms *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_WDA
|
||||
GOptionGroup *qmicli_wda_get_option_group (void);
|
||||
gboolean qmicli_wda_options_enabled (void);
|
||||
void qmicli_wda_run (QmiDevice *device,
|
||||
QmiClientWda *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_VOICE
|
||||
GOptionGroup *qmicli_voice_get_option_group (void);
|
||||
gboolean qmicli_voice_options_enabled (void);
|
||||
void qmicli_voice_run (QmiDevice *device,
|
||||
QmiClientVoice *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_LOC
|
||||
GOptionGroup *qmicli_loc_get_option_group (void);
|
||||
gboolean qmicli_loc_options_enabled (void);
|
||||
void qmicli_loc_run (QmiDevice *device,
|
||||
QmiClientLoc *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_QOS
|
||||
GOptionGroup *qmicli_qos_get_option_group (void);
|
||||
gboolean qmicli_qos_options_enabled (void);
|
||||
void qmicli_qos_run (QmiDevice *device,
|
||||
QmiClientQos *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_GAS
|
||||
GOptionGroup *qmicli_gas_get_option_group (void);
|
||||
gboolean qmicli_gas_options_enabled (void);
|
||||
void qmicli_gas_run (QmiDevice *device,
|
||||
QmiClientGas *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_GMS
|
||||
GOptionGroup *qmicli_gms_get_option_group (void);
|
||||
gboolean qmicli_gms_options_enabled (void);
|
||||
void qmicli_gms_run (QmiDevice *device,
|
||||
QmiClientGms *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_DSD
|
||||
GOptionGroup *qmicli_dsd_get_option_group (void);
|
||||
gboolean qmicli_dsd_options_enabled (void);
|
||||
void qmicli_dsd_run (QmiDevice *device,
|
||||
QmiClientDsd *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_SAR
|
||||
GOptionGroup *qmicli_sar_get_option_group (void);
|
||||
gboolean qmicli_sar_options_enabled (void);
|
||||
void qmicli_sar_run (QmiDevice *device,
|
||||
QmiClientSar *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_DPM
|
||||
GOptionGroup *qmicli_dpm_get_option_group (void);
|
||||
gboolean qmicli_dpm_options_enabled (void);
|
||||
void qmicli_dpm_run (QmiDevice *device,
|
||||
QmiClientDpm *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_FOX
|
||||
GOptionGroup *qmicli_fox_get_option_group (void);
|
||||
gboolean qmicli_fox_options_enabled (void);
|
||||
void qmicli_fox_run (QmiDevice *device,
|
||||
QmiClientFox *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_ATR
|
||||
GOptionGroup *qmicli_atr_get_option_group (void);
|
||||
gboolean qmicli_atr_options_enabled (void);
|
||||
void qmicli_atr_run (QmiDevice *device,
|
||||
QmiClientAtr *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_IMSP
|
||||
GOptionGroup *qmicli_imsp_get_option_group (void);
|
||||
gboolean qmicli_imsp_options_enabled (void);
|
||||
void qmicli_imsp_run (QmiDevice *device,
|
||||
QmiClientImsp *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_IMSA
|
||||
GOptionGroup *qmicli_imsa_get_option_group (void);
|
||||
gboolean qmicli_imsa_options_enabled (void);
|
||||
void qmicli_imsa_run (QmiDevice *device,
|
||||
QmiClientImsa *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_QMI_SERVICE_IMS
|
||||
GOptionGroup *qmicli_ims_get_option_group (void);
|
||||
gboolean qmicli_ims_options_enabled (void);
|
||||
void qmicli_ims_run (QmiDevice *device,
|
||||
QmiClientIms *client,
|
||||
GCancellable *cancellable);
|
||||
#endif
|
||||
|
||||
#endif /* __QMICLI_H__ */
|
Loading…
Reference in New Issue
Block a user