qmi-nmea: remove non-gps parts of qmicli

This commit is contained in:
Daniel Barlow 2024-07-23 21:12:21 +01:00
parent 1a0e19908a
commit 177bd781d7
25 changed files with 3 additions and 26054 deletions

View File

@ -192,6 +192,7 @@ SUBSYSTEM=="wwan", ENV{DEVNAME}=="/dev/wwan0qmi0", ENV{DEVTYPE}=="wwan_port", \
wlr-randr
modemmanager-small
maps
qmi-nmea
];
users.users.dan = {

View File

@ -13,7 +13,7 @@ LDFLAGS=\
default: qmi-nmea
SRCS=qmi-nmea.c qmicli-atr.c qmicli-dms.c qmicli-dpm.c qmicli-dsd.c qmicli-fox.c qmicli-gas.c qmicli-gms.c qmicli-helpers.c qmicli-imsa.c qmicli-ims.c qmicli-imsp.c qmicli-link-management.c qmicli-loc.c qmicli-nas.c qmicli-pbm.c qmicli-pdc.c qmicli-qmiwwan.c qmicli-qos.c qmicli-sar.c qmicli-uim.c qmicli-voice.c qmicli-wda.c qmicli-wds.c qmicli-wms.c
SRCS=qmi-nmea.c qmicli-helpers.c qmicli-loc.c qmi-nmea.c
qmi-nmea: $(patsubst %.c,%.o,$(SRCS))

View File

@ -40,7 +40,7 @@
#include "qmicli.h"
#include "qmicli-helpers.h"
#define PROGRAM_NAME "qmicli"
#define PROGRAM_NAME "qmi-nmea"
#define PROGRAM_VERSION PACKAGE_VERSION
/* Globals */
@ -85,22 +85,6 @@ static GOptionEntry main_entries[] = {
"[PATH]"
#endif
},
{ "get-service-version-info", 0, 0, G_OPTION_ARG_NONE, &get_service_version_info_flag,
"Get service version info",
NULL
},
{ "device-set-instance-id", 0, 0, G_OPTION_ARG_STRING, &device_set_instance_id_str,
"Set instance ID",
"[Instance ID]"
},
{ "device-open-version-info", 0, 0, G_OPTION_ARG_NONE, &device_open_version_info_flag,
"Run version info check when opening device",
NULL
},
{ "device-open-sync", 0, 0, G_OPTION_ARG_NONE, &device_open_sync_flag,
"Run sync operation when opening device",
NULL
},
{ "device-open-proxy", 'p', 0, G_OPTION_ARG_NONE, &device_open_proxy_flag,
"Request to use the 'qmi-proxy' proxy",
NULL
@ -119,10 +103,6 @@ static GOptionEntry main_entries[] = {
NULL
},
#endif
{ "device-open-net", 0, 0, G_OPTION_ARG_STRING, &device_open_net_str,
"Open device with specific link protocol and QoS flags",
"[net-802-3|net-raw-ip|net-qos-header|net-no-qos-header]"
},
{ "client-cid", 0, 0, G_OPTION_ARG_STRING, &client_cid_str,
"Use the given CID, don't allocate a new one",
"[CID]"
@ -139,14 +119,6 @@ static GOptionEntry main_entries[] = {
"Run action with verbose logs, including the debug ones and personal info",
NULL
},
{ "silent", 0, 0, G_OPTION_ARG_NONE, &silent_flag,
"Run action with no logs; not even the error/warning ones",
NULL
},
{ "version", 'V', 0, G_OPTION_ARG_NONE, &version_flag,
"Print version",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
@ -360,69 +332,6 @@ allocate_client_ready (QmiDevice *dev,
/* Run the service-specific action */
switch (service) {
case QMI_SERVICE_DMS:
#if defined HAVE_QMI_SERVICE_DMS
qmicli_dms_run (dev, QMI_CLIENT_DMS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_NAS:
#if defined HAVE_QMI_SERVICE_NAS
qmicli_nas_run (dev, QMI_CLIENT_NAS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_WDS:
#if defined HAVE_QMI_SERVICE_WDS
qmicli_wds_run (dev, QMI_CLIENT_WDS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_PBM:
#if defined HAVE_QMI_SERVICE_PBM
qmicli_pbm_run (dev, QMI_CLIENT_PBM (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_PDC:
#if defined HAVE_QMI_SERVICE_PDC
qmicli_pdc_run (dev, QMI_CLIENT_PDC (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_UIM:
#if defined HAVE_QMI_SERVICE_UIM
qmicli_uim_run (dev, QMI_CLIENT_UIM (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_WMS:
#if defined HAVE_QMI_SERVICE_WMS
qmicli_wms_run (dev, QMI_CLIENT_WMS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_WDA:
#if defined HAVE_QMI_SERVICE_WDA
qmicli_wda_run (dev, QMI_CLIENT_WDA (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_VOICE:
#if defined HAVE_QMI_SERVICE_VOICE
qmicli_voice_run (dev, QMI_CLIENT_VOICE (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_LOC:
#if defined HAVE_QMI_SERVICE_LOC
qmicli_loc_run (dev, QMI_CLIENT_LOC (client), cancellable);
@ -430,115 +339,6 @@ allocate_client_ready (QmiDevice *dev,
#else
break;
#endif
case QMI_SERVICE_QOS:
#if defined HAVE_QMI_SERVICE_QOS
qmicli_qos_run (dev, QMI_CLIENT_QOS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_GAS:
#if defined HAVE_QMI_SERVICE_GAS
qmicli_gas_run (dev, QMI_CLIENT_GAS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_GMS:
#if defined HAVE_QMI_SERVICE_GMS
qmicli_gms_run (dev, QMI_CLIENT_GMS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_DSD:
#if defined HAVE_QMI_SERVICE_DSD
qmicli_dsd_run (dev, QMI_CLIENT_DSD (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_SAR:
#if defined HAVE_QMI_SERVICE_SAR
qmicli_sar_run (dev, QMI_CLIENT_SAR (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_DPM:
#if defined HAVE_QMI_SERVICE_DPM
qmicli_dpm_run (dev, QMI_CLIENT_DPM (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_FOX:
#if defined HAVE_QMI_SERVICE_FOX
qmicli_fox_run (dev, QMI_CLIENT_FOX (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_ATR:
#if defined HAVE_QMI_SERVICE_ATR
qmicli_atr_run (dev, QMI_CLIENT_ATR (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_IMSP:
#if defined HAVE_QMI_SERVICE_IMSP
qmicli_imsp_run (dev, QMI_CLIENT_IMSP (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_IMSA:
#if defined HAVE_QMI_SERVICE_IMSA
qmicli_imsa_run (dev, QMI_CLIENT_IMSA (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_IMS:
#if defined HAVE_QMI_SERVICE_IMS
qmicli_ims_run (dev, QMI_CLIENT_IMS (client), cancellable);
return;
#else
break;
#endif
case QMI_SERVICE_UNKNOWN:
case QMI_SERVICE_CTL:
case QMI_SERVICE_AUTH:
case QMI_SERVICE_AT:
case QMI_SERVICE_CAT2:
case QMI_SERVICE_QCHAT:
case QMI_SERVICE_RMTFS:
case QMI_SERVICE_TEST:
case QMI_SERVICE_ADC:
case QMI_SERVICE_CSD:
case QMI_SERVICE_MFS:
case QMI_SERVICE_TIME:
case QMI_SERVICE_TS:
case QMI_SERVICE_TMD:
case QMI_SERVICE_SAP:
case QMI_SERVICE_TSYNC:
case QMI_SERVICE_RFSA:
case QMI_SERVICE_CSVT:
case QMI_SERVICE_QCMAP:
case QMI_SERVICE_IMSVT:
case QMI_SERVICE_COEX:
case QMI_SERVICE_STX:
case QMI_SERVICE_BIT:
case QMI_SERVICE_IMSRTP:
case QMI_SERVICE_RFRPE:
case QMI_SERVICE_SSCTL:
case QMI_SERVICE_CAT:
case QMI_SERVICE_RMS:
case QMI_SERVICE_FOTA:
case QMI_SERVICE_PDS:
case QMI_SERVICE_OMA:
case QMI_SERVICE_SSC:
default:
break;
}
@ -696,10 +496,6 @@ device_open_ready (QmiDevice *dev,
device_set_instance_id (dev);
else if (get_service_version_info_flag)
device_get_service_version_info (dev);
else if (qmicli_link_management_options_enabled ())
qmicli_link_management_run (dev, cancellable);
else if (qmicli_qmiwwan_options_enabled ())
qmicli_qmiwwan_run (dev, cancellable);
else
device_allocate_client (dev);
}
@ -832,174 +628,12 @@ parse_actions (void)
{
guint actions_enabled = 0;
if (generic_options_enabled ()) {
service = QMI_SERVICE_CTL;
actions_enabled++;
}
if (qmicli_link_management_options_enabled ()) {
service = QMI_SERVICE_UNKNOWN;
actions_enabled++;
}
if (qmicli_qmiwwan_options_enabled ()) {
service = QMI_SERVICE_UNKNOWN;
actions_enabled++;
}
#if defined HAVE_QMI_SERVICE_DMS
if (qmicli_dms_options_enabled ()) {
service = QMI_SERVICE_DMS;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_NAS
if (qmicli_nas_options_enabled ()) {
service = QMI_SERVICE_NAS;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_WDS
if (qmicli_wds_options_enabled ()) {
service = QMI_SERVICE_WDS;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_PBM
if (qmicli_pbm_options_enabled ()) {
service = QMI_SERVICE_PBM;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_PDC
if (qmicli_pdc_options_enabled ()) {
service = QMI_SERVICE_PDC;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_UIM
if (qmicli_uim_options_enabled ()) {
service = QMI_SERVICE_UIM;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_SAR
if (qmicli_sar_options_enabled ()) {
service = QMI_SERVICE_SAR;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_WMS
if (qmicli_wms_options_enabled ()) {
service = QMI_SERVICE_WMS;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_WDA
if (qmicli_wda_options_enabled ()) {
service = QMI_SERVICE_WDA;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_VOICE
if (qmicli_voice_options_enabled ()) {
service = QMI_SERVICE_VOICE;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_LOC
if (qmicli_loc_options_enabled ()) {
service = QMI_SERVICE_LOC;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_QOS
if (qmicli_qos_options_enabled ()) {
service = QMI_SERVICE_QOS;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_GAS
if (qmicli_gas_options_enabled ()) {
service = QMI_SERVICE_GAS;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_GMS
if (qmicli_gms_options_enabled ()) {
service = QMI_SERVICE_GMS;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_DSD
if (qmicli_dsd_options_enabled ()) {
service = QMI_SERVICE_DSD;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_DPM
if (qmicli_dpm_options_enabled ()) {
service = QMI_SERVICE_DPM;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_FOX
if (qmicli_fox_options_enabled ()) {
service = QMI_SERVICE_FOX;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_ATR
if (qmicli_atr_options_enabled ()) {
service = QMI_SERVICE_ATR;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_IMSP
if (qmicli_imsp_options_enabled ()) {
service = QMI_SERVICE_IMSP;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_IMSA
if (qmicli_imsa_options_enabled ()) {
service = QMI_SERVICE_IMSA;
actions_enabled++;
}
#endif
#if defined HAVE_QMI_SERVICE_IMS
if (qmicli_ims_options_enabled ()) {
service = QMI_SERVICE_IMS;
actions_enabled++;
}
#endif
/* Cannot mix actions from different services */
if (actions_enabled > 1) {
g_printerr ("error: cannot execute multiple actions of different services\n");
exit (EXIT_FAILURE);
}
/* No options? */
if (actions_enabled == 0) {
g_printerr ("error: no actions specified\n");
@ -1019,71 +653,9 @@ int main (int argc, char **argv)
/* Setup option context, process it and destroy it */
context = g_option_context_new ("- Control QMI devices");
#if defined HAVE_QMI_SERVICE_DMS
g_option_context_add_group (context, qmicli_dms_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_NAS
g_option_context_add_group (context, qmicli_nas_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_WDS
g_option_context_add_group (context, qmicli_wds_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_PBM
g_option_context_add_group (context, qmicli_pbm_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_PDC
g_option_context_add_group (context, qmicli_pdc_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_UIM
g_option_context_add_group (context, qmicli_uim_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_SAR
g_option_context_add_group (context, qmicli_sar_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_WMS
g_option_context_add_group (context, qmicli_wms_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_WDA
g_option_context_add_group (context, qmicli_wda_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_VOICE
g_option_context_add_group (context, qmicli_voice_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_LOC
g_option_context_add_group (context, qmicli_loc_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_QOS
g_option_context_add_group (context, qmicli_qos_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_GAS
g_option_context_add_group (context, qmicli_gas_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_GMS
g_option_context_add_group (context, qmicli_gms_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_DSD
g_option_context_add_group (context, qmicli_dsd_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_DPM
g_option_context_add_group (context, qmicli_dpm_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_FOX
g_option_context_add_group (context, qmicli_fox_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_ATR
g_option_context_add_group (context, qmicli_atr_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_IMSP
g_option_context_add_group (context, qmicli_imsp_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_IMSA
g_option_context_add_group (context, qmicli_imsa_get_option_group ());
#endif
#if defined HAVE_QMI_SERVICE_IMS
g_option_context_add_group (context, qmicli_ims_get_option_group ());
#endif
g_option_context_add_group (context, qmicli_link_management_get_option_group ());
g_option_context_add_group (context, qmicli_qmiwwan_get_option_group ());
g_option_context_add_main_entries (context, main_entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error)) {
g_printerr ("error: %s\n",

View File

@ -1,413 +0,0 @@
/* -*- 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) 2023 Daniele Palmas <dnlplm@gmail.com>
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <assert.h>
#include <glib.h>
#include <gio/gio.h>
#include <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_ATR
/* Context */
typedef struct {
QmiDevice *device;
QmiClientAtr *client;
GCancellable *cancellable;
guint timeout_id;
guint received_indication_id;
gboolean monitor;
} Context;
static Context *ctx;
/* Options */
static gchar *send_str;
static gchar *send_only_str;
static gboolean monitor_indications_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_ATR_SEND && defined HAVE_QMI_INDICATION_ATR_RECEIVED
{ "atr-send", 0, 0, G_OPTION_ARG_STRING, &send_str,
"Send an AT command and wait for the reply",
"[AT command]"
},
#endif
#if defined HAVE_QMI_MESSAGE_ATR_SEND
{ "atr-send-only", 0, 0, G_OPTION_ARG_STRING, &send_only_str,
"Send an AT command without waiting for the reply",
"[AT command]"
},
#endif
#if defined HAVE_QMI_MESSAGE_ATR_SEND && defined HAVE_QMI_INDICATION_ATR_RECEIVED
{ "atr-monitor", 0, 0, G_OPTION_ARG_NONE, &monitor_indications_flag,
"Watch for unsolicited indications",
NULL
},
#endif
{ "atr-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release an ATR client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_atr_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("atr",
"ATR options:",
"Show AT Relay Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_atr_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (!!send_str +
!!send_only_str +
monitor_indications_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many ATR actions requested\n");
exit (EXIT_FAILURE);
}
/* Actions that require receiving QMI indication messages must specify that
* indications are expected. */
if (!!send_str || monitor_indications_flag)
qmicli_expect_indications ();
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->timeout_id)
g_source_remove (context->timeout_id);
if (context->received_indication_id)
g_signal_handler_disconnect (context->client, context->received_indication_id);
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_ATR_SEND && defined HAVE_QMI_INDICATION_ATR_RECEIVED
/******************************************************************************/
/* Send */
static QmiMessageAtrSendInput *
send_input_create (const gchar *str)
{
QmiMessageAtrSendInput *input = NULL;
input = qmi_message_atr_send_input_new ();
qmi_message_atr_send_input_set_message (input, str, NULL);
return input;
}
static gboolean
send_timed_out (void)
{
ctx->timeout_id = 0;
g_printerr ("error: operation failed: timeout\n");
operation_shutdown (FALSE);
return G_SOURCE_REMOVE;
}
static gboolean
is_final_response (const gchar *reply)
{
/* The following regexes are taken from MM serial parser */
GRegexCompileFlags flags = G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW | G_REGEX_OPTIMIZE;
g_autoptr(GRegex) regex_ok = NULL;
g_autoptr(GRegex) regex_connect = NULL;
g_autoptr(GRegex) regex_cme_error = NULL;
g_autoptr(GRegex) regex_cms_error = NULL;
g_autoptr(GRegex) regex_unknown_error = NULL;
g_autoptr(GRegex) regex_connect_failed = NULL;
regex_ok = g_regex_new ("\\r\\nOK(\\r\\n)+", flags, 0, NULL);
regex_connect = g_regex_new ("\\r\\nCONNECT.*\\r\\n", flags, 0, NULL);
regex_cme_error = g_regex_new ("\\r\\n\\+CME ERROR*\\r\\n", flags, 0, NULL);
regex_cms_error = g_regex_new ("\\r\\n\\+CMS ERROR*\\r\\n", flags, 0, NULL);
regex_unknown_error = g_regex_new ("\\r\\n(ERROR)|(COMMAND NOT SUPPORT)\\r\\n", flags, 0, NULL);
regex_connect_failed = g_regex_new ("\\r\\n(NO CARRIER)|(BUSY)|(NO ANSWER)|(NO DIALTONE)\\r\\n", flags, 0, NULL);
if (g_regex_match_full (regex_ok,
reply, strlen (reply),
0, 0, NULL, NULL) ||
g_regex_match_full (regex_unknown_error,
reply, strlen (reply),
0, 0, NULL, NULL) ||
g_regex_match_full (regex_cme_error,
reply, strlen (reply),
0, 0, NULL, NULL) ||
g_regex_match_full (regex_cms_error,
reply, strlen (reply),
0, 0, NULL, NULL) ||
g_regex_match_full (regex_connect,
reply, strlen (reply),
0, 0, NULL, NULL) ||
g_regex_match_full (regex_connect_failed,
reply, strlen (reply),
0, 0, NULL, NULL))
return TRUE;
return FALSE;
}
static void
indication_received (QmiClientAtr *client,
QmiIndicationAtrReceivedOutput *output)
{
const gchar *received;
g_autoptr(GError) error = NULL;
if (!qmi_indication_atr_received_output_get_message (output, &received, &error)) {
g_printerr ("error: couldn't get indication message: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (ctx->monitor) {
/* When monitoring we don't want to print final responses
* e.g. the initial ATE0 reply or the ones for the commands sent with
* atr-send-only using the same cid
* The comparison with "ATE0" is for avoid printing the echo of the
* mandatory initial command */
if (!is_final_response (received) && g_strcmp0 (received, "ATE0\r"))
g_print ("%s", received);
} else {
/* No need to print an additional '\n', since the indication already has '\r\n' */
g_print ("%s", received);
/* The reply can arrive with multiple indications, so we need to check if the
* indication has the final response */
if (is_final_response (received)) {
g_print ("Successfully received final response\n");
operation_shutdown (TRUE);
}
}
}
static void
monitoring_cancelled (GCancellable *cancellable)
{
operation_shutdown (TRUE);
}
static void
send_ready (QmiClientAtr *client,
GAsyncResult *res)
{
g_autoptr(QmiMessageAtrSendOutput) output = NULL;
g_autoptr(GError) error = NULL;
output = qmi_client_atr_send_finish (client, res, &error);
if (!output) {
g_printerr ("error: operation failed: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_atr_send_output_get_result (output, &error)) {
g_printerr ("error: couldn't send AT command: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (ctx->monitor) {
/* User can use Ctrl+C to cancel the monitoring at any time */
g_cancellable_connect (ctx->cancellable,
G_CALLBACK (monitoring_cancelled),
NULL,
NULL);
g_print ("Monitoring unsolicited indications: press Ctrl+C to stop\n");
} else
/* Wait for the response asynchronously: 120 seconds should be enough also
* for long-lasting commands (e.g. AT+COPS=?) */
ctx->timeout_id = g_timeout_add_seconds (120,
(GSourceFunc) send_timed_out,
NULL);
ctx->received_indication_id = g_signal_connect (ctx->client,
"received",
G_CALLBACK (indication_received),
NULL);
}
#endif /* HAVE_QMI_MESSAGE_ATR_SEND
* HAVE_QMI_INDICATION_ATR_RECEIVED */
#if defined HAVE_QMI_MESSAGE_ATR_SEND
/******************************************************************************/
/* Send and don't wait for the reply */
static void
send_only_ready (QmiClientAtr *client,
GAsyncResult *res)
{
g_autoptr(QmiMessageAtrSendOutput) output = NULL;
g_autoptr(GError) error = NULL;
output = qmi_client_atr_send_finish (client, res, &error);
if (!output) {
g_printerr ("error: operation failed: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_atr_send_output_get_result (output, &error)) {
g_printerr ("error: couldn't send AT command: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
g_print ("Successfully sent AT command\n");
operation_shutdown (TRUE);
}
static void
generic_send (const gchar *cmd,
GAsyncReadyCallback cb)
{
g_autofree gchar *at_cmd = NULL;
g_autoptr(QmiMessageAtrSendInput) input = NULL;
g_debug ("Asynchronously sending AT command...");
at_cmd = g_strconcat (cmd, "\r", NULL);
input = send_input_create (at_cmd);
if (!input) {
operation_shutdown (FALSE);
return;
}
qmi_client_atr_send (ctx->client,
input,
10,
ctx->cancellable,
cb,
NULL);
}
#endif /* HAVE_QMI_MESSAGE_ATR_SEND */
/******************************************************************************/
/* Common */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_atr_run (QmiDevice *device,
QmiClientAtr *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);
#if defined HAVE_QMI_MESSAGE_ATR_SEND && defined HAVE_QMI_INDICATION_ATR_RECEIVED
if (send_str) {
generic_send (send_str, (GAsyncReadyCallback)send_ready);
return;
}
if (monitor_indications_flag) {
/* To really open the AT communication and receive unsolicited
* indications it is mandatory to send an initial AT command.
* The command ATE0 has been chosen so that, if needed, commands
* can be sent by a different qmicli instance reusing the monitoring
* cid with --atr-send-only. This avoids also polluting the monitoring
* operation with the comands echo */
ctx->monitor = TRUE;
generic_send ("ATE0", (GAsyncReadyCallback)send_ready);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_ATR_SEND
if (send_only_str) {
generic_send (send_only_str, (GAsyncReadyCallback)send_only_ready);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_ATR */

File diff suppressed because it is too large Load Diff

View File

@ -1,544 +0,0 @@
/* -*- 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) 2021 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"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_DPM
#define QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED -1
/* Context */
typedef struct {
QmiDevice *device;
QmiClientDpm *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gchar *open_port_str;
static gboolean close_port_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_DPM_OPEN_PORT
{ "dpm-open-port", 0, 0, G_OPTION_ARG_STRING, &open_port_str,
"Open port (allowed-keys: ctrl-ep-type, ctrl-ep-iface-number, ctrl-port-name, hw-data-ep-type, hw-data-ep-iface-number, hw-data-rx-id, hw-data-tx-id, sw-data-ep-type, sw-data-ep-iface-number, sw-data-port-name)",
"[\"key=value,...\"]"
},
#endif
#if defined HAVE_QMI_MESSAGE_DPM_CLOSE_PORT
{ "dpm-close-port", 0, 0, G_OPTION_ARG_NONE, &close_port_flag,
"Close port",
NULL
},
#endif
{ "dpm-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a DPM client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_dpm_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("dpm",
"DPM options:",
"Show Data Port Mapper Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_dpm_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (!!open_port_str +
close_port_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many DPM actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_DPM_OPEN_PORT
static void
open_port_ready (QmiClientDpm *client,
GAsyncResult *res)
{
g_autoptr(QmiMessageDpmOpenPortOutput) output = NULL;
g_autoptr(GError) error = NULL;
output = qmi_client_dpm_open_port_finish (client, res, &error);
if (!output) {
g_printerr ("error: operation failed: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_dpm_open_port_output_get_result (output, &error)) {
g_printerr ("error: couldn't open port: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
g_print ("Successfully opened the port\n");
operation_shutdown (TRUE);
}
typedef struct {
/* control port item building */
GArray *ctrl_ports;
QmiDataEndpointType ctrl_ep_type;
gint ctrl_ep_iface_number;
gchar *ctrl_port_name;
/* hw data port item building */
GArray *hw_data_ports;
QmiDataEndpointType hw_data_ep_type;
gint hw_data_ep_iface_number;
guint hw_data_rx_id;
guint hw_data_tx_id;
/* sw data port item building */
GArray *sw_data_ports;
QmiDataEndpointType sw_data_ep_type;
gint sw_data_ep_iface_number;
gchar *sw_data_port_name;
} OpenPortProperties;
static void
reset_ctrl_port_item (OpenPortProperties *props)
{
g_free (props->ctrl_port_name);
props->ctrl_port_name = NULL;
props->ctrl_ep_type = QMI_DATA_ENDPOINT_TYPE_UNKNOWN;
props->ctrl_ep_iface_number = QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED;
}
static void
ctrl_port_details_clear (QmiMessageDpmOpenPortInputControlPortsElement *details)
{
g_free (details->port_name);
}
static void
build_ctrl_port_item (OpenPortProperties *props)
{
if ((props->ctrl_ep_type != QMI_DATA_ENDPOINT_TYPE_UNKNOWN) &&
(props->ctrl_ep_iface_number != QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) &&
(props->ctrl_port_name != NULL)) {
QmiMessageDpmOpenPortInputControlPortsElement details;
details.port_name = g_strdup (props->ctrl_port_name);
details.endpoint_type = props->ctrl_ep_type;
details.interface_number = props->ctrl_ep_iface_number;
if (!props->ctrl_ports) {
props->ctrl_ports = g_array_new (FALSE, FALSE, sizeof (QmiMessageDpmOpenPortInputControlPortsElement));
g_array_set_clear_func (props->ctrl_ports, (GDestroyNotify)ctrl_port_details_clear);
}
g_array_append_val (props->ctrl_ports, details);
reset_ctrl_port_item (props);
}
}
static gboolean
check_unfinished_ctrl_port_item (OpenPortProperties *props,
GError **error)
{
if ((props->ctrl_ep_type != QMI_DATA_ENDPOINT_TYPE_UNKNOWN) ||
(props->ctrl_ep_iface_number != QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) ||
(props->ctrl_port_name != NULL)) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"error: unfinished ctrl port item");
return FALSE;
}
return TRUE;
}
static void
reset_hw_data_port_item (OpenPortProperties *props)
{
props->hw_data_rx_id = 0;
props->hw_data_tx_id = 0;
props->hw_data_ep_type = QMI_DATA_ENDPOINT_TYPE_UNKNOWN;
props->hw_data_ep_iface_number = QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED;
}
static void
build_hw_data_port_item (OpenPortProperties *props)
{
if ((props->hw_data_ep_type != QMI_DATA_ENDPOINT_TYPE_UNKNOWN) &&
(props->hw_data_ep_iface_number != QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) &&
(props->hw_data_rx_id != 0) &&
(props->hw_data_tx_id != 0)) {
QmiMessageDpmOpenPortInputHardwareDataPortsElement details;
details.rx_endpoint_number = props->hw_data_rx_id;
details.tx_endpoint_number = props->hw_data_tx_id;
details.endpoint_type = props->hw_data_ep_type;
details.interface_number = props->hw_data_ep_iface_number;
if (!props->hw_data_ports)
props->hw_data_ports = g_array_new (FALSE, FALSE, sizeof (QmiMessageDpmOpenPortInputHardwareDataPortsElement));
g_array_append_val (props->hw_data_ports, details);
reset_hw_data_port_item (props);
}
}
static gboolean
check_unfinished_hw_data_port_item (OpenPortProperties *props,
GError **error)
{
if ((props->hw_data_ep_type != QMI_DATA_ENDPOINT_TYPE_UNKNOWN) ||
(props->hw_data_ep_iface_number != QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) ||
(props->hw_data_rx_id != 0) ||
(props->hw_data_tx_id != 0)) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"error: unfinished hw data port item");
return FALSE;
}
return TRUE;
}
static void
reset_sw_data_port_item (OpenPortProperties *props)
{
g_free (props->sw_data_port_name);
props->sw_data_port_name = NULL;
props->sw_data_ep_type = QMI_DATA_ENDPOINT_TYPE_UNKNOWN;
props->sw_data_ep_iface_number = QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED;
}
static void
sw_data_port_details_clear (QmiMessageDpmOpenPortInputSoftwareDataPortsElement *details)
{
g_free (details->port_name);
}
static void
build_sw_data_port_item (OpenPortProperties *props)
{
if ((props->sw_data_ep_type != QMI_DATA_ENDPOINT_TYPE_UNKNOWN) &&
(props->sw_data_ep_iface_number != QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) &&
(props->sw_data_port_name != NULL)) {
QmiMessageDpmOpenPortInputSoftwareDataPortsElement details;
details.port_name = g_strdup (props->sw_data_port_name);
details.endpoint_type = props->sw_data_ep_type;
details.interface_number = props->sw_data_ep_iface_number;
if (!props->sw_data_ports) {
props->sw_data_ports = g_array_new (FALSE, FALSE, sizeof (QmiMessageDpmOpenPortInputSoftwareDataPortsElement));
g_array_set_clear_func (props->sw_data_ports, (GDestroyNotify)sw_data_port_details_clear);
}
g_array_append_val (props->sw_data_ports, details);
reset_sw_data_port_item (props);
}
}
static gboolean
check_unfinished_sw_data_port_item (OpenPortProperties *props,
GError **error)
{
if ((props->sw_data_ep_type != QMI_DATA_ENDPOINT_TYPE_UNKNOWN) ||
(props->sw_data_ep_iface_number != QMI_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) ||
(props->sw_data_port_name != NULL)) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"error: unfinished sw data port item");
return FALSE;
}
return TRUE;
}
static gboolean
open_port_properties_handle (const gchar *key,
const gchar *value,
GError **error,
gpointer user_data)
{
OpenPortProperties *props = (OpenPortProperties *)user_data;
if (!value || !value[0]) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"key '%s' requires a value", key);
return FALSE;
}
/* control port item */
if (g_ascii_strcasecmp (key, "ctrl-ep-type") == 0) {
if (!qmicli_read_data_endpoint_type_from_string (value, &(props->ctrl_ep_type))) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"Unrecognized Endpoint Type '%s'", value);
return FALSE;
}
build_ctrl_port_item (props);
return TRUE;
}
if (g_ascii_strcasecmp (key, "ctrl-ep-iface-number") == 0) {
props->ctrl_ep_iface_number = atoi (value);
build_ctrl_port_item (props);
return TRUE;
}
if (g_ascii_strcasecmp (key, "ctrl-port-name") == 0) {
g_clear_pointer (&props->ctrl_port_name, g_free);
props->ctrl_port_name = g_strdup (value);
build_ctrl_port_item (props);
return TRUE;
}
/* hw data port item */
if (g_ascii_strcasecmp (key, "hw-data-ep-type") == 0) {
if (!qmicli_read_data_endpoint_type_from_string (value, &(props->hw_data_ep_type))) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"Unrecognized Endpoint Type '%s'", value);
return FALSE;
}
build_hw_data_port_item (props);
return TRUE;
}
if (g_ascii_strcasecmp (key, "hw-data-ep-iface-number") == 0) {
props->hw_data_ep_iface_number = atoi (value);
build_hw_data_port_item (props);
return TRUE;
}
if (g_ascii_strcasecmp (key, "hw-data-rx-id") == 0) {
props->hw_data_rx_id = atoi (value);
build_hw_data_port_item (props);
return TRUE;
}
if (g_ascii_strcasecmp (key, "hw-data-tx-id") == 0) {
props->hw_data_tx_id = atoi (value);
build_hw_data_port_item (props);
return TRUE;
}
/* sw data port item */
if (g_ascii_strcasecmp (key, "sw-data-ep-type") == 0) {
if (!qmicli_read_data_endpoint_type_from_string (value, &(props->sw_data_ep_type))) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"Unrecognized Endpoint Type '%s'", value);
return FALSE;
}
build_sw_data_port_item (props);
return TRUE;
}
if (g_ascii_strcasecmp (key, "sw-data-ep-iface-number") == 0) {
props->sw_data_ep_iface_number = atoi (value);
build_sw_data_port_item (props);
return TRUE;
}
if (g_ascii_strcasecmp (key, "sw-data-port-name") == 0) {
g_clear_pointer (&props->sw_data_port_name, g_free);
props->sw_data_port_name = g_strdup (value);
build_sw_data_port_item (props);
return TRUE;
}
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"Unrecognized option '%s'", key);
return FALSE;
}
static gboolean
open_port_input_create (const gchar *str,
QmiMessageDpmOpenPortInput **out_input,
GError **error)
{
QmiMessageDpmOpenPortInput *input;
OpenPortProperties props = { 0 };
reset_ctrl_port_item (&props);
reset_hw_data_port_item (&props);
reset_sw_data_port_item (&props);
if (!qmicli_parse_key_value_string (str, error, open_port_properties_handle, &props))
return FALSE;
if (!check_unfinished_ctrl_port_item (&props, error) ||
!check_unfinished_hw_data_port_item (&props, error) ||
!check_unfinished_sw_data_port_item (&props, error))
return FALSE;
input = qmi_message_dpm_open_port_input_new ();
if (props.ctrl_ports) {
qmi_message_dpm_open_port_input_set_control_ports (input, props.ctrl_ports, NULL);
g_clear_pointer (&props.ctrl_ports, g_array_unref);
}
if (props.hw_data_ports) {
qmi_message_dpm_open_port_input_set_hardware_data_ports (input, props.hw_data_ports, NULL);
g_clear_pointer (&props.hw_data_ports, g_array_unref);
}
if (props.sw_data_ports) {
qmi_message_dpm_open_port_input_set_software_data_ports (input, props.sw_data_ports, NULL);
g_clear_pointer (&props.sw_data_ports, g_array_unref);
}
*out_input = input;
return TRUE;
}
#endif /* HAVE_QMI_MESSAGE_DPM_OPEN_PORT */
#if defined HAVE_QMI_MESSAGE_DPM_CLOSE_PORT
static void
close_port_ready (QmiClientDpm *client,
GAsyncResult *res)
{
g_autoptr(QmiMessageDpmClosePortOutput) output = NULL;
g_autoptr(GError) error = NULL;
output = qmi_client_dpm_close_port_finish (client, res, &error);
if (!output) {
g_printerr ("error: operation failed: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_dpm_close_port_output_get_result (output, &error)) {
g_printerr ("error: couldn't close port: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
g_print ("Successfully closeed the port\n");
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_DPM_CLOSE_PORT */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_dpm_run (QmiDevice *device,
QmiClientDpm *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_DPM_OPEN_PORT
if (open_port_str) {
g_autoptr(QmiMessageDpmOpenPortInput) input = NULL;
g_autoptr(GError) error = NULL;
if (!open_port_input_create (open_port_str, &input, &error)) {
g_printerr ("error: couldn't process input arguments: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
qmi_client_dpm_open_port (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)open_port_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_DPM_CLOSE_PORT
if (close_port_flag) {
qmi_client_dpm_close_port (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)close_port_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_DPM */

View File

@ -1,415 +0,0 @@
/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es>
* Copyright (c) 2022 Qualcomm Innovation Center, Inc.
*/
#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"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_DSD
#undef VALIDATE_MASK_NONE
#define VALIDATE_MASK_NONE(str) (str ? str : "none")
/* Context */
typedef struct {
QmiDevice *device;
QmiClientDsd *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gchar *get_apn_info_str;
static gchar *set_apn_type_str;
static gboolean get_system_status_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_DSD_GET_APN_INFO
{ "dsd-get-apn-info", 0, 0, G_OPTION_ARG_STRING, &get_apn_info_str,
"Gets the settings associated to a given APN type",
"[(type)]"
},
#endif
#if defined HAVE_QMI_MESSAGE_DSD_SET_APN_TYPE
{ "dsd-set-apn-type", 0, 0, G_OPTION_ARG_STRING, &set_apn_type_str,
"Sets the types associated to a given APN name",
"[(name), (type1|type2|type3...)]"
},
#endif
#if defined HAVE_QMI_MESSAGE_DSD_GET_SYSTEM_STATUS
{ "dsd-get-system-status", 0, 0, G_OPTION_ARG_NONE, &get_system_status_flag,
"Gets system status",
NULL
},
#endif
{ "dsd-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a DSD client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_dsd_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("dsd",
"DSD options:",
"Show Data System Determination options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_dsd_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (!!get_apn_info_str +
!!set_apn_type_str +
get_system_status_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many DSD actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_DSD_GET_APN_INFO
static void
get_apn_info_ready (QmiClientDsd *client,
GAsyncResult *res)
{
QmiMessageDsdGetApnInfoOutput *output;
GError *error = NULL;
const gchar *apn_name = NULL;
output = qmi_client_dsd_get_apn_info_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_dsd_get_apn_info_output_get_result (output, &error)) {
g_printerr ("error: couldn't get APN info: %s\n", error->message);
g_error_free (error);
qmi_message_dsd_get_apn_info_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("APN info found:\n");
if (qmi_message_dsd_get_apn_info_output_get_apn_name (output, &apn_name, NULL))
g_print ("APN name: %s\n", apn_name);
else
g_print ("APN name: n/a\n");
qmi_message_dsd_get_apn_info_output_unref (output);
operation_shutdown (TRUE);
}
static QmiMessageDsdGetApnInfoInput *
get_apn_info_input_create (const gchar *str)
{
QmiMessageDsdGetApnInfoInput *input = NULL;
GError *error = NULL;
QmiDsdApnType apn_type;
if (!qmicli_read_dsd_apn_type_from_string (str, &apn_type)) {
g_printerr ("error: couldn't parse input string as APN type: '%s'\n", str);
return NULL;
}
input = qmi_message_dsd_get_apn_info_input_new ();
if (!qmi_message_dsd_get_apn_info_input_set_apn_type (input, apn_type, &error)) {
g_printerr ("error: couldn't create input data bundle: '%s'\n",
error->message);
g_error_free (error);
qmi_message_dsd_get_apn_info_input_unref (input);
input = NULL;
}
return input;
}
#endif /* HAVE_QMI_MESSAGE_DSD_GET_APN_INFO */
#if defined HAVE_QMI_MESSAGE_DSD_SET_APN_TYPE
static void
set_apn_type_ready (QmiClientDsd *client,
GAsyncResult *res)
{
QmiMessageDsdSetApnTypeOutput *output;
GError *error = NULL;
output = qmi_client_dsd_set_apn_type_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_dsd_set_apn_type_output_get_result (output, &error)) {
g_printerr ("error: couldn't set APN type: %s\n", error->message);
g_error_free (error);
qmi_message_dsd_set_apn_type_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("APN type set\n");
qmi_message_dsd_set_apn_type_output_unref (output);
operation_shutdown (TRUE);
}
static QmiMessageDsdSetApnTypeInput *
set_apn_type_input_create (const gchar *str)
{
QmiMessageDsdSetApnTypeInput *input = NULL;
GError *error = NULL;
QmiDsdApnTypePreference apn_type_preference;
gchar **split;
split = g_strsplit_set (str, ",", 0);
if (g_strv_length (split) != 2) {
g_printerr ("input string requires 2 values, %u given: '%s'\n", g_strv_length (split), str);
g_strfreev (split);
return NULL;
}
g_strstrip (split[0]);
g_strstrip (split[1]);
if (!qmicli_read_dsd_apn_type_preference_from_string (split[1], &apn_type_preference)) {
g_printerr ("error: couldn't parse input string as APN type preference mask: '%s'\n", split[1]);
g_strfreev (split);
return NULL;
}
input = qmi_message_dsd_set_apn_type_input_new ();
if (!qmi_message_dsd_set_apn_type_input_set_apn_type (input, split[0], apn_type_preference, &error)) {
g_printerr ("error: couldn't create input data bundle: '%s'\n",
error->message);
g_error_free (error);
qmi_message_dsd_set_apn_type_input_unref (input);
input = NULL;
}
g_strfreev (split);
return input;
}
#endif /* HAVE_QMI_MESSAGE_DSD_SET_APN_TYPE */
#if defined HAVE_QMI_MESSAGE_DSD_GET_SYSTEM_STATUS
static void
get_system_status_ready (QmiClientDsd *client,
GAsyncResult *res)
{
QmiMessageDsdGetSystemStatusOutput *output;
GError *error = NULL;
GArray *available_systems = NULL;
guint i;
output = qmi_client_dsd_get_system_status_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_dsd_get_system_status_output_get_result (output, &error)) {
g_printerr ("error: couldn't get system status: %s\n", error->message);
g_error_free (error);
qmi_message_dsd_get_system_status_output_unref (output);
operation_shutdown (FALSE);
return;
}
qmi_message_dsd_get_system_status_output_get_available_systems (output, &available_systems, NULL);
if (!available_systems || !available_systems->len) {
g_print ("No available data system\n");
} else {
g_print ("Available data systems retrieved:\n");
for (i = 0; i < available_systems->len; i++) {
QmiMessageDsdGetSystemStatusOutputAvailableSystemsSystem *system;
g_autofree gchar *so_mask_str = NULL;
system = &g_array_index (available_systems, QmiMessageDsdGetSystemStatusOutputAvailableSystemsSystem, i);
so_mask_str = qmi_dsd_so_mask_build_string_from_mask ((QmiDsdSoMask)system->so_mask);
g_print ("System [%u]%s:\n"
"\tNetwork type: '%s'\n"
"\tRAT: '%s'\n"
"\tService option: '%s'\n",
i,
i > 0 ? "" : " (current preferred)",
qmi_dsd_data_system_network_type_get_string (system->technology),
qmi_dsd_radio_access_technology_get_string (system->rat),
VALIDATE_MASK_NONE (so_mask_str));
}
}
qmi_message_dsd_get_system_status_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_DSD_GET_SYSTEM_STATUS */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_dsd_run (QmiDevice *device,
QmiClientDsd *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_DSD_GET_APN_INFO
if (get_apn_info_str) {
QmiMessageDsdGetApnInfoInput *input;
g_debug ("Asynchronously getting APN info...");
input = get_apn_info_input_create (get_apn_info_str);
if (!input) {
operation_shutdown (FALSE);
return;
}
qmi_client_dsd_get_apn_info (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_apn_info_ready,
NULL);
qmi_message_dsd_get_apn_info_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_DSD_SET_APN_TYPE
if (set_apn_type_str) {
QmiMessageDsdSetApnTypeInput *input;
g_debug ("Asynchronously setting APN type...");
input = set_apn_type_input_create (set_apn_type_str);
if (!input) {
operation_shutdown (FALSE);
return;
}
qmi_client_dsd_set_apn_type (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)set_apn_type_ready,
NULL);
qmi_message_dsd_set_apn_type_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_DSD_GET_SYSTEM_STATUS
if (get_system_status_flag) {
g_debug ("Asynchronously getting system status...");
qmi_client_dsd_get_system_status (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_system_status_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_DSD */

View File

@ -1,240 +0,0 @@
/* -*- 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) 2022 Freedom Liu <lk@linuxdev.top>
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <assert.h>
#include <glib.h>
#include <gio/gio.h>
#include <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_FOX
#undef VALIDATE_UNKNOWN
#define VALIDATE_UNKNOWN(str) (str ? str : "unknown")
/* Context */
typedef struct {
QmiDevice *device;
QmiClientFox *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gchar *get_firmware_version_str;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_FOX_GET_FIRMWARE_VERSION
{ "fox-get-firmware-version", 0, 0, G_OPTION_ARG_STRING, &get_firmware_version_str,
"Get firmware version",
"[firmware-mcfg-apps|firmware-mcfg|apps]"
},
#endif
{ "fox-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a FOX client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_fox_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("fox",
"FOX options:",
"Show Foxconn Modem Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_fox_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (!!get_firmware_version_str +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many FOX actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_FOX_GET_FIRMWARE_VERSION
static QmiMessageFoxGetFirmwareVersionInput *
get_firmware_version_input_create (const gchar *str)
{
QmiMessageFoxGetFirmwareVersionInput *input = NULL;
QmiFoxFirmwareVersionType type;
GError *error = NULL;
if (!qmicli_read_fox_firmware_version_type_from_string (str, &type)) {
g_printerr ("error: couldn't parse input firmware version type : '%s'\n", str);
return NULL;
}
input = qmi_message_fox_get_firmware_version_input_new ();
if (!qmi_message_fox_get_firmware_version_input_set_version_type (input, type, &error)) {
g_printerr ("error: couldn't create input data bundle: '%s'\n",
error->message);
g_error_free (error);
qmi_message_fox_get_firmware_version_input_unref (input);
return NULL;
}
return input;
}
static void
get_firmware_version_ready (QmiClientFox *client,
GAsyncResult *res)
{
const gchar *str = NULL;
QmiMessageFoxGetFirmwareVersionOutput *output;
GError *error = NULL;
output = qmi_client_fox_get_firmware_version_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_fox_get_firmware_version_output_get_result (output, &error)) {
g_printerr ("error: couldn't get firmware version: %s\n", error->message);
g_error_free (error);
qmi_message_fox_get_firmware_version_output_unref (output);
operation_shutdown (FALSE);
return;
}
qmi_message_fox_get_firmware_version_output_get_version (output, &str, NULL);
g_print ("[%s] Firmware version retrieved:\n"
"\tVersion: '%s'\n",
qmi_device_get_path_display (ctx->device),
VALIDATE_UNKNOWN (str));
qmi_message_fox_get_firmware_version_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_FOX_GET_FIRMWARE_VERSION */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_fox_run (QmiDevice *device,
QmiClientFox *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_FOX_GET_FIRMWARE_VERSION
if (get_firmware_version_str) {
QmiMessageFoxGetFirmwareVersionInput *input;
g_debug ("Asynchronously getting firmware version...");
input = get_firmware_version_input_create (get_firmware_version_str);
if (!input) {
operation_shutdown (FALSE);
return;
}
qmi_client_fox_get_firmware_version (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_firmware_version_ready,
NULL);
qmi_message_fox_get_firmware_version_input_unref (input);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_FOX */

View File

@ -1,499 +0,0 @@
/* -*- 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) 2019 Andreas Kling <awesomekling@gmail.com>
*/
#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 <qmi-common.h>
#include "qmicli.h"
#if defined HAVE_QMI_SERVICE_GAS
/* Context */
typedef struct {
QmiDevice *device;
QmiClientGas *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gboolean get_firmware_list_flag;
static gboolean get_active_firmware_flag;
static gint set_active_firmware_int = -1;
static gint set_usb_composition_int = -1;
static gboolean get_usb_composition_flag;
static gboolean get_ethernet_mac_address_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_GAS_DMS_SET_USB_COMPOSITION
{ "gas-dms-set-usb-composition", 0, 0, G_OPTION_ARG_INT, &set_usb_composition_int,
"Sets the USB composition",
"[pid]"
},
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_USB_COMPOSITION
{ "gas-dms-get-usb-composition", 0, 0, G_OPTION_ARG_NONE, &get_usb_composition_flag,
"Gets the current USB composition",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_FIRMWARE_LIST
{ "gas-dms-get-firmware-list", 0, 0, G_OPTION_ARG_NONE, &get_firmware_list_flag,
"Gets the list of stored firmware",
NULL
},
{ "gas-dms-get-active-firmware", 0, 0, G_OPTION_ARG_NONE, &get_active_firmware_flag,
"Gets the currently active firmware",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_SET_ACTIVE_FIRMWARE
{ "gas-dms-set-active-firmware", 0, 0, G_OPTION_ARG_INT, &set_active_firmware_int,
"Sets the active firmware index",
"[index]"
},
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_ETHERNET_PDU_MAC_ADDRESS
{ "gas-dms-get-ethernet-mac-address", 0, 0, G_OPTION_ARG_NONE, &get_ethernet_mac_address_flag,
"Gets the Ethernet PDU MAC address available in the modem",
NULL
},
#endif
{ "gas-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a GAS client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_gas_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("gas",
"GAS options:",
"Show General Application Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_gas_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = ((set_usb_composition_int >= 0) +
get_usb_composition_flag +
get_firmware_list_flag +
get_active_firmware_flag +
(set_active_firmware_int >= 0) +
get_ethernet_mac_address_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many GAS actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_GAS_DMS_SET_USB_COMPOSITION
static void
set_usb_composition_ready (QmiClientGas *client,
GAsyncResult *res)
{
QmiMessageGasDmsSetUsbCompositionOutput *output;
GError *error = NULL;
output = qmi_client_gas_dms_set_usb_composition_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_gas_dms_set_usb_composition_output_get_result (output, &error)) {
g_printerr ("error: unable to switch composition: %s\n", error->message);
g_error_free (error);
qmi_message_gas_dms_set_usb_composition_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully switched composition.\n",
qmi_device_get_path_display (ctx->device));
qmi_message_gas_dms_set_usb_composition_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_GAS_DMS_SET_USB_COMPOSITION */
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_USB_COMPOSITION
static void
get_usb_composition_ready (QmiClientGas *client,
GAsyncResult *res)
{
QmiMessageGasDmsGetUsbCompositionOutput *output;
GError *error = NULL;
guint32 composition;
output = qmi_client_gas_dms_get_usb_composition_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_gas_dms_get_usb_composition_output_get_result (output, &error)) {
g_printerr ("error: unable to get current composition: %s\n", error->message);
g_error_free (error);
qmi_message_gas_dms_get_usb_composition_output_unref (output);
operation_shutdown (FALSE);
return;
}
qmi_message_gas_dms_get_usb_composition_output_get_usb_composition (output, &composition, NULL);
g_print ("[%s] Current composition is 0x%x\n",
qmi_device_get_path_display (ctx->device),
composition);
qmi_message_gas_dms_get_usb_composition_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_GAS_DMS_GET_USB_COMPOSITION */
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_FIRMWARE_LIST
static void
print_firmware_listing (guint8 idx,
const gchar *name,
const gchar *version,
const gchar *pri_revision)
{
g_print ("Firmware #%u:\n"
"\tIndex: %u\n"
"\tName: %s\n"
"\tVersion: %s\n"
"\tPRI revision: %s\n",
idx,
idx,
name,
version,
pri_revision);
}
static void
get_firmware_list_ready (QmiClientGas *client,
GAsyncResult *res)
{
QmiMessageGasDmsGetFirmwareListOutput *output;
GError *error = NULL;
guint8 idx;
const gchar *name;
const gchar *version;
const gchar *pri_revision;
output = qmi_client_gas_dms_get_firmware_list_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_gas_dms_get_firmware_list_output_get_result (output, &error)) {
g_printerr ("error: couldn't get stored firmware list: %s\n", error->message);
g_error_free (error);
qmi_message_gas_dms_get_firmware_list_output_unref (output);
operation_shutdown (FALSE);
return;
}
if (qmi_message_gas_dms_get_firmware_list_output_get_stored_firmware_1 (output, &idx, &name, &version, &pri_revision, NULL))
print_firmware_listing (idx, name, version, pri_revision);
if (qmi_message_gas_dms_get_firmware_list_output_get_stored_firmware_2 (output, &idx, &name, &version, &pri_revision, NULL))
print_firmware_listing (idx, name, version, pri_revision);
if (qmi_message_gas_dms_get_firmware_list_output_get_stored_firmware_3 (output, &idx, &name, &version, &pri_revision, NULL))
print_firmware_listing (idx, name, version, pri_revision);
if (qmi_message_gas_dms_get_firmware_list_output_get_stored_firmware_4 (output, &idx, &name, &version, &pri_revision, NULL))
print_firmware_listing (idx, name, version, pri_revision);
qmi_message_gas_dms_get_firmware_list_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_GAS_DMS_GET_FIRMWARE_LIST */
#if defined HAVE_QMI_MESSAGE_GAS_DMS_SET_ACTIVE_FIRMWARE
static void
set_active_firmware_ready (QmiClientGas *client,
GAsyncResult *res)
{
QmiMessageGasDmsSetActiveFirmwareOutput *output;
GError *error = NULL;
output = qmi_client_gas_dms_set_active_firmware_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_gas_dms_set_active_firmware_output_get_result (output, &error)) {
g_printerr ("error: couldn't set active firmware list: %s\n", error->message);
g_error_free (error);
qmi_message_gas_dms_set_active_firmware_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("Successfully set the active firmware.\n");
qmi_message_gas_dms_set_active_firmware_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_GAS_DMS_SET_ACTIVE_FIRMWARE */
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_ETHERNET_PDU_MAC_ADDRESS
static void
print_mac_address (GArray *address)
{
g_autofree gchar *str = NULL;
str = qmi_common_str_hex (address->data, address->len, ':');
g_print ("%s\n", str);
}
static void
get_ethernet_pdu_mac_address_ready (QmiClientGas *client,
GAsyncResult *res)
{
g_autoptr(QmiMessageGasDmsGetEthernetPduMacAddressOutput) output;
g_autoptr(GError) error = NULL;
GArray *address;
output = qmi_client_gas_dms_get_ethernet_pdu_mac_address_finish (client, res, &error);
if (!output) {
g_printerr ("error: operation failed: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_gas_dms_get_ethernet_pdu_mac_address_output_get_result (output, &error)) {
g_printerr ("error: couldn't get Ethernet PDU MAC address: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (qmi_message_gas_dms_get_ethernet_pdu_mac_address_output_get_mac_address_0 (output, &address, &error)) {
g_print ("Ethernet MAC address 0: ");
print_mac_address (address);
} else {
g_printerr ("error: couldn't get Ethernet PDU MAC address 0: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (qmi_message_gas_dms_get_ethernet_pdu_mac_address_output_get_mac_address_1 (output, &address, NULL)) {
g_print ("Ethernet MAC address 1: ");
print_mac_address (address);
}
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_GAS_DMS_GET_ETHERNET_PDU_MAC_ADDRESS */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_gas_run (QmiDevice *device,
QmiClientGas *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_GAS_DMS_SET_USB_COMPOSITION
if (set_usb_composition_int >= 0) {
QmiMessageGasDmsSetUsbCompositionInput *input;
input = qmi_message_gas_dms_set_usb_composition_input_new ();
qmi_message_gas_dms_set_usb_composition_input_set_usb_composition (input, set_usb_composition_int, NULL);
qmi_message_gas_dms_set_usb_composition_input_set_endpoint_type (input, QMI_GAS_USB_COMPOSITION_ENDPOINT_TYPE_HSUSB, NULL);
qmi_message_gas_dms_set_usb_composition_input_set_composition_persistence (input, TRUE, NULL);
qmi_message_gas_dms_set_usb_composition_input_set_immediate_setting (input, FALSE, NULL);
qmi_message_gas_dms_set_usb_composition_input_set_reboot_after_setting (input, TRUE, NULL);
g_debug ("Asynchronously switching the USB composition...");
qmi_client_gas_dms_set_usb_composition (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)set_usb_composition_ready,
NULL);
qmi_message_gas_dms_set_usb_composition_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_USB_COMPOSITION
if (get_usb_composition_flag) {
g_debug ("Asynchronously getting the USB composition...");
qmi_client_gas_dms_get_usb_composition (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_usb_composition_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_FIRMWARE_LIST
if (get_firmware_list_flag || get_active_firmware_flag) {
QmiMessageGasDmsGetFirmwareListInput *input;
input = qmi_message_gas_dms_get_firmware_list_input_new ();
if (get_firmware_list_flag) {
g_debug ("Asynchronously getting full firmware list...");
qmi_message_gas_dms_get_firmware_list_input_set_mode (input, QMI_GAS_FIRMWARE_LISTING_MODE_ALL_FIRMWARE, NULL);
} else if (get_active_firmware_flag) {
g_debug ("Asynchronously getting active firmware list...");
qmi_message_gas_dms_get_firmware_list_input_set_mode (input, QMI_GAS_FIRMWARE_LISTING_MODE_ACTIVE_FIRMWARE, NULL);
} else
g_assert_not_reached ();
qmi_client_gas_dms_get_firmware_list (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_firmware_list_ready,
NULL);
qmi_message_gas_dms_get_firmware_list_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_SET_ACTIVE_FIRMWARE
if (set_active_firmware_int >= 0) {
QmiMessageGasDmsSetActiveFirmwareInput *input;
input = qmi_message_gas_dms_set_active_firmware_input_new ();
qmi_message_gas_dms_set_active_firmware_input_set_slot_index (input, set_active_firmware_int, NULL);
g_debug ("Asynchronously setting the active firmware index...");
qmi_client_gas_dms_set_active_firmware (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)set_active_firmware_ready,
NULL);
qmi_message_gas_dms_set_active_firmware_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_GAS_DMS_GET_ETHERNET_PDU_MAC_ADDRESS
if (get_ethernet_mac_address_flag) {
g_debug ("Asynchronously getting ethernet mac adress...");
qmi_client_gas_dms_get_ethernet_pdu_mac_address (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_ethernet_pdu_mac_address_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_GAS */

View File

@ -1,316 +0,0 @@
/* -*- 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) 2020 Vladimir Podshivalov <vladimir.podshivalov@outlook.com>
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <assert.h>
#include <glib.h>
#include <gio/gio.h>
#include <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_GMS
/* Context */
typedef struct {
QmiDevice *device;
QmiClientGms *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gboolean get_value_flag;
static gchar *set_value_str;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_GMS_TEST_GET_VALUE
{ "gms-test-get-value", 0, 0, G_OPTION_ARG_NONE, &get_value_flag,
"Gets test value",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_GMS_TEST_SET_VALUE
{ "gms-test-set-value", 0, 0, G_OPTION_ARG_STRING, &set_value_str,
"Sets test value",
"[mandatory-value][,[optional-value]]"
},
#endif
{ "gms-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a GMS client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_gms_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("gms",
"GMS options:",
"Show General Modem Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_gms_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (get_value_flag +
!!set_value_str +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many GMS actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_GMS_TEST_GET_VALUE
static void
get_value_ready (QmiClientGms *client,
GAsyncResult *res)
{
QmiMessageGmsTestGetValueOutput *output;
GError *error = NULL;
guint8 test_mandatory_value;
guint8 test_optional_value;
output = qmi_client_gms_test_get_value_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_gms_test_get_value_output_get_result (output, &error)) {
g_printerr ("error: couldn't get stored test value: %s\n", error->message);
g_error_free (error);
qmi_message_gms_test_get_value_output_unref (output);
operation_shutdown (FALSE);
return;
}
if (qmi_message_gms_test_get_value_output_get_test_mandatory_value (output, &test_mandatory_value, NULL)) {
g_print ("Test mandatory value: %u\n", test_mandatory_value);
}
if (qmi_message_gms_test_get_value_output_get_test_optional_value (output, &test_optional_value, NULL)) {
g_print ("Test optional value: %u\n", test_optional_value);
}
qmi_message_gms_test_get_value_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_GMS_TEST_GET_VALUE */
#if defined HAVE_QMI_MESSAGE_GMS_TEST_SET_VALUE
static QmiMessageGmsTestSetValueInput *
set_value_input_create (const gchar *str)
{
QmiMessageGmsTestSetValueInput *input = NULL;
const gchar *mand_value_str = NULL;
const gchar *opt_value_str = NULL;
guint mand_value_int = 0;
guint opt_value_int = 0;
gchar **parts = NULL;
if (strchr (str, ',')) {
/* Both Mandatory Test Value and Optional Test Value were given */
parts = g_strsplit_set (str, ",", -1);
if (g_strv_length (parts) != 2) {
g_printerr ("error: failed to parse test value: '%s'\n", str);
goto out;
}
mand_value_str = parts[0];
opt_value_str = parts[1];
} else {
/* Only Mandatory Test Value was given */
mand_value_str = str;
}
g_assert (mand_value_str);
if (!qmicli_read_uint_from_string (mand_value_str, &mand_value_int) || (mand_value_int > G_MAXUINT8)) {
g_printerr ("error: failed to parse test mandatory value as 8bit value: '%s'\n", mand_value_str);
goto out;
}
if (opt_value_str && (!qmicli_read_uint_from_string (opt_value_str, &opt_value_int) || (opt_value_int > G_MAXUINT8))) {
g_printerr ("error: failed to parse test optional value as 8bit value: '%s'\n", opt_value_str);
goto out;
}
input = qmi_message_gms_test_set_value_input_new ();
qmi_message_gms_test_set_value_input_set_test_mandatory_value (input, (guint8) mand_value_int, NULL);
if (opt_value_str) {
qmi_message_gms_test_set_value_input_set_test_optional_value (input, (guint8) opt_value_int, NULL);
}
out:
g_strfreev (parts);
return input;
}
static void
set_value_ready (QmiClientGms *client,
GAsyncResult *res)
{
QmiMessageGmsTestSetValueOutput *output;
GError *error = NULL;
output = qmi_client_gms_test_set_value_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_gms_test_set_value_output_get_result (output, &error)) {
g_printerr ("error: couldn't set test value: %s\n", error->message);
g_error_free (error);
qmi_message_gms_test_set_value_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("Successfully set test value.\n");
qmi_message_gms_test_set_value_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_GMS_TEST_SET_VALUE */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_gms_run (QmiDevice *device,
QmiClientGms *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_GMS_TEST_GET_VALUE
if (get_value_flag) {
g_debug ("Asynchronously getting test value...");
qmi_client_gms_test_get_value (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_value_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_GMS_TEST_SET_VALUE
if (set_value_str) {
QmiMessageGmsTestSetValueInput *input;
g_debug ("Asynchronously setting test value...");
input = set_value_input_create (set_value_str);
if (!input) {
operation_shutdown (FALSE);
return;
}
qmi_client_gms_test_set_value (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)set_value_ready,
NULL);
qmi_message_gms_test_set_value_input_unref (input);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_GMS */

View File

@ -1,283 +0,0 @@
/* -*- 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) 2023 Dylan Van Assche <me@dylanvanassche.be>
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <assert.h>
#include <glib.h>
#include <gio/gio.h>
#include <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_IMS
/* Context */
typedef struct {
QmiDevice *device;
QmiClientIms *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gint bind_flag = -1;
static gboolean get_services_enabled_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_IMS_BIND
{ "ims-bind", 0, 0, G_OPTION_ARG_INT, &bind_flag,
"Bind to IMS Settings (use with --client-no-release-cid)",
"[binding]"
},
#endif
#if defined HAVE_QMI_MESSAGE_IMS_GET_IMS_SERVICES_ENABLED_SETTING
{ "ims-get-ims-services-enabled-setting", 0, 0, G_OPTION_ARG_NONE, &get_services_enabled_flag,
"Get IMS Services Enabled Setting",
NULL
},
#endif
{ "ims-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a IMS client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL }
};
GOptionGroup *
qmicli_ims_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("ims",
"IMS options:",
"Show IP Multimedia Subsystem Settings Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_ims_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = ((bind_flag >= 0) +
get_services_enabled_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many IMS actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_IMS_BIND
static void
bind_ready (QmiClientIms *client,
GAsyncResult *res)
{
QmiMessageImsBindOutput *output;
g_autoptr(GError) error = NULL;
output = qmi_client_ims_bind_finish (client, res, &error);
if (!output) {
g_printerr ("error: operation failed: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_ims_bind_output_get_result (output, &error)) {
g_printerr ("error: couldn't bind to IMS Settings: %s\n", error->message);
qmi_message_ims_bind_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] IMS Settings bind successful\n", qmi_device_get_path_display (ctx->device));
qmi_message_ims_bind_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_IMS_BIND */
#if defined HAVE_QMI_MESSAGE_IMS_GET_IMS_SERVICES_ENABLED_SETTING
static void
get_services_enabled_ready (QmiClientIms *client,
GAsyncResult *res)
{
QmiMessageImsGetImsServicesEnabledSettingOutput *output;
gboolean service_voice_enabled;
gboolean service_vt_enabled;
gboolean service_voice_wifi_enabled;
gboolean service_ims_registration_enabled;
gboolean service_ut_enabled;
gboolean service_sms_enabled;
gboolean service_ussd_enabled;
GError *error = NULL;
output = qmi_client_ims_get_ims_services_enabled_setting_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_ims_get_ims_services_enabled_setting_output_get_result (output, &error)) {
g_printerr ("error: couldn't get IMS services enabled setting: %s\n", error->message);
g_error_free (error);
qmi_message_ims_get_ims_services_enabled_setting_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] IMS services:\n", qmi_device_get_path_display (ctx->device));
if (qmi_message_ims_get_ims_services_enabled_setting_output_get_ims_voice_service_enabled (output, &service_voice_enabled, NULL))
g_print ("\t Voice service enabled: %s\n", service_voice_enabled? "yes" : "no");
if (qmi_message_ims_get_ims_services_enabled_setting_output_get_ims_video_telephony_service_enabled (output, &service_vt_enabled, NULL))
g_print ("\tVideo Telephony service enabled: %s\n", service_vt_enabled? "yes" : "no");
if (qmi_message_ims_get_ims_services_enabled_setting_output_get_ims_voice_wifi_service_enabled (output, &service_voice_wifi_enabled, NULL))
g_print ("\t Voice WiFi service enabled: %s\n", service_voice_wifi_enabled? "yes" : "no");
if (qmi_message_ims_get_ims_services_enabled_setting_output_get_ims_registration_service_enabled (output, &service_ims_registration_enabled, NULL))
g_print ("\t IMS registration enabled: %s\n", service_ims_registration_enabled? "yes" : "no");
if (qmi_message_ims_get_ims_services_enabled_setting_output_get_ims_ut_service_enabled (output, &service_ut_enabled, NULL))
g_print ("\t UE to TAS service enabled: %s\n", service_ut_enabled? "yes" : "no");
if (qmi_message_ims_get_ims_services_enabled_setting_output_get_ims_sms_service_enabled (output, &service_sms_enabled, NULL))
g_print ("\t SMS service enabled: %s\n", service_sms_enabled? "yes" : "no");
if (qmi_message_ims_get_ims_services_enabled_setting_output_get_ims_ussd_service_enabled (output, &service_ussd_enabled, NULL))
g_print ("\t USSD service enabled: %s\n", service_ut_enabled? "yes" : "no");
qmi_message_ims_get_ims_services_enabled_setting_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_IMS_GET_IMS_SERVICES_ENABLED_SETTING */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_ims_run (QmiDevice *device,
QmiClientIms *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_IMS_BIND
if (bind_flag >= 0) {
QmiMessageImsBindInput *input;
input = qmi_message_ims_bind_input_new ();
qmi_message_ims_bind_input_set_binding (input, bind_flag, NULL);
g_debug ("Asynchronously binding to IMS settings service...");
qmi_client_ims_bind (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)bind_ready,
NULL);
qmi_message_ims_bind_input_unref (input);
return;
}
#endif /* HAVE_QMI_MESSAGE_IMS_BIND */
#if defined HAVE_QMI_MESSAGE_IMS_GET_IMS_SERVICES_ENABLED_SETTING
if (get_services_enabled_flag) {
g_debug ("Asynchronously getting services enabled setting...");
qmi_client_ims_get_ims_services_enabled_setting (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_services_enabled_ready,
NULL);
return;
}
#endif /* HAVE_QMI_MESSAGE_IMS_GET_IMS_SERVICES_ENABLED_SETTING */
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_IMS */

View File

@ -1,367 +0,0 @@
/* -*- 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) 2023 Dylan Van Assche <me@dylanvanassche.be>
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <assert.h>
#include <glib.h>
#include <gio/gio.h>
#include <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_IMSA
/* Context */
typedef struct {
QmiDevice *device;
QmiClientImsa *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gint bind_flag = -1;
static gboolean get_ims_registration_status_flag;
static gboolean get_ims_services_status_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_IMSA_BIND
{ "imsa-bind", 0, 0, G_OPTION_ARG_INT, &bind_flag,
"Bind to IMSA (use with --client-no-release-cid)",
"[binding]"
},
#endif
#if defined HAVE_QMI_MESSAGE_IMSA_GET_IMS_REGISTRATION_STATUS
{ "imsa-get-ims-registration-status", 0, 0, G_OPTION_ARG_NONE, &get_ims_registration_status_flag,
"Get IMS registration status",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_IMSA_GET_IMS_SERVICES_STATUS
{ "imsa-get-ims-services-status", 0, 0, G_OPTION_ARG_NONE, &get_ims_services_status_flag,
"Get IMS services status",
NULL
},
#endif
{ "imsa-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a IMSA client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL }
};
GOptionGroup *
qmicli_imsa_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("imsa",
"IMSA options:",
"Show IP Multimedia Subsystem Application Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_imsa_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = ((bind_flag >= 0) +
get_ims_registration_status_flag +
get_ims_services_status_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many IMSA actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_IMSA_BIND
static void
bind_ready (QmiClientImsa *client,
GAsyncResult *res)
{
QmiMessageImsaBindOutput *output;
g_autoptr(GError) error = NULL;
output = qmi_client_imsa_bind_finish (client, res, &error);
if (!output) {
g_printerr ("error: operation failed: %s\n", error->message);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_imsa_bind_output_get_result (output, &error)) {
g_printerr ("error: couldn't bind to IMSA: %s\n", error->message);
qmi_message_imsa_bind_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] IMSA bind successful\n", qmi_device_get_path_display (ctx->device));
qmi_message_imsa_bind_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_IMSA_BIND */
#if defined HAVE_QMI_MESSAGE_IMSA_GET_IMS_REGISTRATION_STATUS
static void
get_ims_registration_status_ready (QmiClientImsa *client,
GAsyncResult *res)
{
QmiMessageImsaGetImsRegistrationStatusOutput *output;
QmiImsaImsRegistrationStatus registration_status;
QmiImsaRegistrationTechnology registration_technology;
GError *error = NULL;
output = qmi_client_imsa_get_ims_registration_status_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_imsa_get_ims_registration_status_output_get_result (output, &error)) {
g_printerr ("error: couldn't get IMS registration status: %s\n", error->message);
g_error_free (error);
qmi_message_imsa_get_ims_registration_status_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] IMS registration:\n", qmi_device_get_path_display (ctx->device));
if (qmi_message_imsa_get_ims_registration_status_output_get_ims_registration_status (output, &registration_status, NULL))
g_print ("\t Status: '%s'\n", qmi_imsa_ims_registration_status_get_string (registration_status));
if (qmi_message_imsa_get_ims_registration_status_output_get_ims_registration_technology (output, &registration_technology, NULL))
g_print ("\tTechnology: '%s'\n", qmi_imsa_registration_technology_get_string (registration_technology));
qmi_message_imsa_get_ims_registration_status_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_IMSA_GET_IMS_REGISTRATION_STATUS */
#if defined HAVE_QMI_MESSAGE_IMSA_GET_IMS_SERVICES_STATUS
static void
get_ims_services_status_ready (QmiClientImsa *client,
GAsyncResult *res)
{
QmiMessageImsaGetImsServicesStatusOutput *output;
QmiImsaServiceStatus service_sms_status;
QmiImsaRegistrationTechnology service_sms_technology;
QmiImsaServiceStatus service_voice_status;
QmiImsaRegistrationTechnology service_voice_technology;
QmiImsaServiceStatus service_vt_status;
QmiImsaRegistrationTechnology service_vt_technology;
QmiImsaServiceStatus service_ut_status;
QmiImsaRegistrationTechnology service_ut_technology;
QmiImsaServiceStatus service_vs_status;
QmiImsaRegistrationTechnology service_vs_technology;
GError *error = NULL;
output = qmi_client_imsa_get_ims_services_status_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_imsa_get_ims_services_status_output_get_result (output, &error)) {
g_printerr ("error: couldn't get IMS services status: %s\n", error->message);
g_error_free (error);
qmi_message_imsa_get_ims_services_status_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] IMS services:\n", qmi_device_get_path_display (ctx->device));
g_print ("\tSMS service\n");
if (qmi_message_imsa_get_ims_services_status_output_get_ims_sms_service_status (output, &service_sms_status, NULL))
g_print ("\t\t Status: '%s'\n", qmi_imsa_service_status_get_string (service_sms_status));
if (qmi_message_imsa_get_ims_services_status_output_get_ims_sms_service_registration_technology (output, &service_sms_technology, NULL))
g_print ("\t\tTechnology: '%s'\n", qmi_imsa_registration_technology_get_string (service_sms_technology));
g_print ("\tVoice service\n");
if (qmi_message_imsa_get_ims_services_status_output_get_ims_voice_service_status (output, &service_voice_status, NULL))
g_print ("\t\t Status: '%s'\n", qmi_imsa_service_status_get_string (service_voice_status));
if (qmi_message_imsa_get_ims_services_status_output_get_ims_voice_service_registration_technology (output, &service_voice_technology, NULL))
g_print ("\t\tTechnology: '%s'\n", qmi_imsa_registration_technology_get_string (service_voice_technology));
g_print ("\tVideo Telephony service\n");
if (qmi_message_imsa_get_ims_services_status_output_get_ims_video_telephony_service_status (output, &service_vt_status, NULL))
g_print ("\t\t Status: '%s'\n", qmi_imsa_service_status_get_string (service_vt_status));
if (qmi_message_imsa_get_ims_services_status_output_get_ims_video_telephony_service_registration_technology (output, &service_vt_technology, NULL))
g_print ("\t\tTechnology: '%s'\n", qmi_imsa_registration_technology_get_string (service_vt_technology));
g_print ("\tUE to TAS service\n");
if (qmi_message_imsa_get_ims_services_status_output_get_ims_ue_to_tas_service_status (output, &service_ut_status, NULL))
g_print ("\t\t Status: '%s'\n", qmi_imsa_service_status_get_string (service_ut_status));
if (qmi_message_imsa_get_ims_services_status_output_get_ims_ue_to_tas_service_registration_technology (output, &service_ut_technology, NULL))
g_print ("\t\tTechnology: '%s'\n", qmi_imsa_registration_technology_get_string (service_ut_technology));
g_print ("\tVideo Share service\n");
if (qmi_message_imsa_get_ims_services_status_output_get_ims_video_share_service_status (output, &service_vs_status, NULL))
g_print ("\t\t Status: '%s'\n", qmi_imsa_service_status_get_string (service_vs_status));
if (qmi_message_imsa_get_ims_services_status_output_get_ims_video_share_service_registration_technology (output, &service_vs_technology, NULL))
g_print ("\t\tTechnology: '%s'\n", qmi_imsa_registration_technology_get_string (service_vs_technology));
qmi_message_imsa_get_ims_services_status_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_IMSA_GET_IMS_SERVICES_STATUS */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_imsa_run (QmiDevice *device,
QmiClientImsa *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_IMSA_BIND
if (bind_flag >= 0) {
QmiMessageImsaBindInput *input;
input = qmi_message_imsa_bind_input_new ();
qmi_message_imsa_bind_input_set_binding (input, bind_flag, NULL);
g_debug ("Asynchronously binding to IMSA service...");
qmi_client_imsa_bind (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)bind_ready,
NULL);
qmi_message_imsa_bind_input_unref (input);
return;
}
#endif /* HAVE_QMI_MESSAGE_IMSA_BIND */
#if defined HAVE_QMI_MESSAGE_IMSA_GET_IMS_REGISTRATION_STATUS
if (get_ims_registration_status_flag) {
g_debug ("Asynchronously getting IMS registration status...");
qmi_client_imsa_get_ims_registration_status (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_ims_registration_status_ready,
NULL);
return;
}
#endif /* HAVE_QMI_MESSAGE_IMSA_GET_IMS_REGISTRATION_STATUS */
#if defined HAVE_QMI_MESSAGE_IMSA_GET_IMS_SERVICES_STATUS
if (get_ims_services_status_flag) {
g_debug ("Asynchronously getting IMS services status...");
qmi_client_imsa_get_ims_services_status (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_ims_services_status_ready,
NULL);
return;
}
#endif /* HAVE_QMI_MESSAGE_IMSA_GET_IMS_SERVICES_STATUS */
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_IMSA */

View File

@ -1,205 +0,0 @@
/* -*- 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) 2023 Dylan Van Assche <me@dylanvanassche.be>
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <assert.h>
#include <glib.h>
#include <gio/gio.h>
#include <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_IMSP
/* Context */
typedef struct {
QmiDevice *device;
QmiClientImsp *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gboolean get_enabler_state_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_IMSP_GET_ENABLER_STATE
{ "imsp-get-enabler-state", 0, 0, G_OPTION_ARG_NONE, &get_enabler_state_flag,
"Get IMSP enabler state",
NULL
},
#endif
{ "imsp-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a IMSP client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL }
};
GOptionGroup *
qmicli_imsp_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("imsp",
"IMSP options:",
"Show IP Multimedia Subsystem Presence Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_imsp_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (get_enabler_state_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many IMSP actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_IMSP_GET_ENABLER_STATE
static void
get_enabler_state_ready (QmiClientImsp *client,
GAsyncResult *res)
{
QmiMessageImspGetEnablerStateOutput *output;
QmiImspEnablerState enabler_state;
GError *error = NULL;
output = qmi_client_imsp_get_enabler_state_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_imsp_get_enabler_state_output_get_result (output, &error)) {
g_printerr ("error: couldn't get enabler state: %s\n", error->message);
g_error_free (error);
qmi_message_imsp_get_enabler_state_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] IMSP enabler state retrieved:\n", qmi_device_get_path_display (ctx->device));
if (qmi_message_imsp_get_enabler_state_output_get_enabler_state (output, &enabler_state, NULL)) {
g_print ("\tRegistration status: '%s'\n",
qmi_imsp_enabler_state_get_string (enabler_state));
}
qmi_message_imsp_get_enabler_state_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_IMSP_GET_ENABLER_STATE */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_imsp_run (QmiDevice *device,
QmiClientImsp *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_IMSP_GET_ENABLER_STATE
if (get_enabler_state_flag) {
g_debug ("Asynchronously getting enabler state...");
qmi_client_imsp_get_enabler_state (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_enabler_state_ready,
NULL);
return;
}
#endif /* HAVE_QMI_MESSAGE_IMSP_GET_ENABLER_STATE */
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_IMSP */

View File

@ -1,386 +0,0 @@
/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es>
*/
#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 <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
/* Options */
static gchar *link_list_str;
static gchar *link_add_str;
static gchar *link_delete_str;
static gchar *link_delete_all_str;
static GOptionEntry entries[] = {
{ "link-list", 0, 0, G_OPTION_ARG_STRING, &link_list_str,
"List links created from a given interface",
"[IFACE]"
},
{ "link-add", 0, 0, G_OPTION_ARG_STRING, &link_add_str,
"Create new network interface link",
"[iface=IFACE,prefix=PREFIX[,mux-id=N][,flags=FLAGS]]"
},
{ "link-delete", 0, 0, G_OPTION_ARG_STRING, &link_delete_str,
"Delete a given network interface link",
"[link-iface=IFACE][,[mux-id=N]]"
},
{ "link-delete-all", 0, 0, G_OPTION_ARG_STRING, &link_delete_all_str,
"Delete all network interface links from the given interface",
"[IFACE]"
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_link_management_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("link-management",
"Link management options:",
"Show link management specific options",
NULL, NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_link_management_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (!!link_list_str +
!!link_add_str +
!!link_delete_str +
!!link_delete_all_str);
if (n_actions > 1) {
g_printerr ("error: too many link management actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
/******************************************************************************/
static void
link_delete_all_ready (QmiDevice *dev,
GAsyncResult *res)
{
g_autoptr(GError) error = NULL;
if (!qmi_device_delete_all_links_finish (dev, res, &error))
g_printerr ("error: couldn't delete all links: %s\n", error->message);
else
g_print ("[%s] all links successfully deleted\n",
qmi_device_get_path_display (dev));
qmicli_async_operation_done (!error, FALSE);
}
static void
device_link_delete_all (QmiDevice *dev,
GCancellable *cancellable,
const gchar *iface)
{
qmi_device_delete_all_links (dev,
iface,
cancellable,
(GAsyncReadyCallback)link_delete_all_ready,
NULL);
}
typedef struct {
guint mux_id;
gchar *link_iface;
} DeleteLinkProperties;
static void
link_delete_ready (QmiDevice *dev,
GAsyncResult *res)
{
g_autoptr(GError) error = NULL;
if (!qmi_device_delete_link_finish (dev, res, &error))
g_printerr ("error: couldn't delete link: %s\n",
error->message);
else
g_print ("[%s] link successfully deleted\n",
qmi_device_get_path_display (dev));
qmicli_async_operation_done (!error, FALSE);
}
static gboolean
del_link_properties_handle (const gchar *key,
const gchar *value,
GError **error,
DeleteLinkProperties *props)
{
if (g_ascii_strcasecmp (key, "mux-id") == 0 && props->mux_id == QMI_DEVICE_MUX_ID_UNBOUND) {
if (!qmicli_read_uint_from_string (value, &props->mux_id)) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"invalid mux-id given: '%s'", value);
return FALSE;
}
return TRUE;
}
if (g_ascii_strcasecmp (key, "link-iface") == 0 && !props->link_iface) {
props->link_iface = g_strdup (value);
return TRUE;
}
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"unrecognized or duplicate option '%s'", key);
return FALSE;
}
static void
device_link_delete (QmiDevice *dev,
GCancellable *cancellable,
const gchar *del_settings)
{
g_autoptr(GError) error = NULL;
DeleteLinkProperties props = {
.mux_id = QMI_DEVICE_MUX_ID_UNBOUND,
.link_iface = NULL,
};
if (!qmicli_parse_key_value_string (del_settings,
&error,
(QmiParseKeyValueForeachFn)del_link_properties_handle,
&props)) {
g_printerr ("error: couldn't parse input add link settings: %s\n",
error->message);
qmicli_async_operation_done (FALSE, FALSE);
return;
}
if (!props.link_iface) {
g_printerr ("error: missing mandatory 'link-iface' setting\n");
qmicli_async_operation_done (FALSE, FALSE);
return;
}
if ((props.mux_id != QMI_DEVICE_MUX_ID_UNBOUND) &&
(props.mux_id < QMI_DEVICE_MUX_ID_MIN || props.mux_id > QMI_DEVICE_MUX_ID_MAX)) {
g_printerr ("error: mux id %u out of range [%u,%u]\n",
props.mux_id, QMI_DEVICE_MUX_ID_MIN, QMI_DEVICE_MUX_ID_MAX);
qmicli_async_operation_done (FALSE, FALSE);
return;
}
qmi_device_delete_link (dev,
props.link_iface,
props.mux_id,
cancellable,
(GAsyncReadyCallback)link_delete_ready,
NULL);
g_free (props.link_iface);
}
typedef struct {
guint mux_id;
gchar *iface;
gchar *prefix;
QmiDeviceAddLinkFlags flags;
} AddLinkProperties;
static void
link_add_ready (QmiDevice *dev,
GAsyncResult *res)
{
g_autoptr(GError) error = NULL;
g_autofree gchar *link_iface = NULL;
guint mux_id;
link_iface = qmi_device_add_link_with_flags_finish (dev, res, &mux_id, &error);
if (!link_iface)
g_printerr ("error: couldn't add link: %s\n",
error->message);
else
g_print ("[%s] link successfully added:\n"
" iface name: %s\n"
" mux-id: %u\n",
qmi_device_get_path_display (dev),
link_iface,
mux_id);
qmicli_async_operation_done (!error, FALSE);
}
static gboolean
add_link_properties_handle (const gchar *key,
const gchar *value,
GError **error,
AddLinkProperties *props)
{
if (g_ascii_strcasecmp (key, "mux-id") == 0 && props->mux_id == QMI_DEVICE_MUX_ID_AUTOMATIC) {
if (!qmicli_read_uint_from_string (value, &props->mux_id)) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"invalid mux-id given: '%s'", value);
return FALSE;
}
return TRUE;
}
if (g_ascii_strcasecmp (key, "iface") == 0 && !props->iface) {
props->iface = g_strdup (value);
return TRUE;
}
if (g_ascii_strcasecmp (key, "prefix") == 0 && !props->prefix) {
props->prefix = g_strdup (value);
return TRUE;
}
if (g_ascii_strcasecmp (key, "flags") == 0 && !props->flags) {
if (!qmicli_read_device_add_link_flags_from_string (value, &props->flags)) {
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"invalid flags given: '%s'", value);
return FALSE;
}
return TRUE;
}
g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
"unrecognized or duplicate option '%s'", key);
return FALSE;
}
static void
device_link_add (QmiDevice *dev,
GCancellable *cancellable,
const gchar *add_settings)
{
g_autoptr(GError) error = NULL;
AddLinkProperties props = {
.mux_id = QMI_DEVICE_MUX_ID_AUTOMATIC,
.iface = NULL,
.prefix = NULL,
.flags = QMI_DEVICE_ADD_LINK_FLAGS_NONE,
};
if (!qmicli_parse_key_value_string (add_settings,
&error,
(QmiParseKeyValueForeachFn)add_link_properties_handle,
&props)) {
g_printerr ("error: couldn't parse input add link settings: %s\n",
error->message);
qmicli_async_operation_done (FALSE, FALSE);
return;
}
if (!props.iface) {
g_printerr ("error: missing mandatory 'iface' setting\n");
qmicli_async_operation_done (FALSE, FALSE);
return;
}
if (!props.prefix)
props.prefix = g_strdup_printf ("%s.", props.iface);
if ((props.mux_id != QMI_DEVICE_MUX_ID_AUTOMATIC) &&
(props.mux_id < QMI_DEVICE_MUX_ID_MIN || props.mux_id > QMI_DEVICE_MUX_ID_MAX)) {
g_printerr ("error: mux id %u out of range [%u,%u]\n",
props.mux_id, QMI_DEVICE_MUX_ID_MIN, QMI_DEVICE_MUX_ID_MAX);
qmicli_async_operation_done (FALSE, FALSE);
return;
}
qmi_device_add_link_with_flags (dev,
props.mux_id,
props.iface,
props.prefix,
props.flags,
cancellable,
(GAsyncReadyCallback)link_add_ready,
NULL);
g_free (props.iface);
g_free (props.prefix);
}
static void
device_link_list (QmiDevice *dev,
GCancellable *cancellable,
const gchar *iface)
{
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) links = NULL;
if (!qmi_device_list_links (dev, iface, &links, &error))
g_printerr ("error: couldn't list links: %s\n", error->message);
else {
guint i;
guint n_links;
n_links = (links ? links->len : 0);
g_print ("[%s] found %u links%s\n",
qmi_device_get_path_display (dev),
n_links,
n_links > 0 ? ":" : "");
for (i = 0; i < n_links; i++)
g_print (" [%u] %s\n", i, (const gchar *) g_ptr_array_index (links, i));
}
qmicli_async_operation_done (!error, FALSE);
}
/******************************************************************************/
/* Common */
void
qmicli_link_management_run (QmiDevice *dev,
GCancellable *cancellable)
{
if (link_list_str)
device_link_list (dev, cancellable, link_list_str);
else if (link_add_str)
device_link_add (dev, cancellable, link_add_str);
else if (link_delete_str)
device_link_delete (dev, cancellable, link_delete_str);
else if (link_delete_all_str)
device_link_delete_all (dev, cancellable, link_delete_all_str);
else
g_warn_if_reached ();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,349 +0,0 @@
/* -*- 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) 2013-2017 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_PBM
#undef VALIDATE_MASK_NONE
#define VALIDATE_MASK_NONE(str) (str ? str : "none")
/* Context */
typedef struct {
QmiDevice *device;
QmiClientPbm *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gboolean get_all_capabilities_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_PBM_GET_ALL_CAPABILITIES
{ "pbm-get-all-capabilities", 0, 0, G_OPTION_ARG_NONE, &get_all_capabilities_flag,
"Get all phonebook capabilities",
NULL
},
#endif
{ "pbm-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a PBM client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_pbm_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("pbm",
"PBM options:",
"Show Phonebook Management options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_pbm_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (get_all_capabilities_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many PBM actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->client)
g_object_unref (context->client);
g_object_unref (context->cancellable);
g_object_unref (context->device);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_PBM_GET_ALL_CAPABILITIES
static void
get_all_capabilities_ready (QmiClientPbm *client,
GAsyncResult *res)
{
GError *error = NULL;
QmiMessagePbmGetAllCapabilitiesOutput *output;
GArray *capability_basic_information = NULL;
GArray *group_capability = NULL;
GArray *additional_number_capability = NULL;
GArray *email_capability = NULL;
GArray *second_name_capability = NULL;
GArray *hidden_records_capability = NULL;
GArray *grouping_information_alpha_string_capability = NULL;
GArray *additional_number_alpha_string_capability = NULL;
guint i, j;
output = qmi_client_pbm_get_all_capabilities_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_pbm_get_all_capabilities_output_get_result (output, &error)) {
g_printerr ("error: couldn't get capabilities: %s\n", error->message);
g_error_free (error);
qmi_message_pbm_get_all_capabilities_output_unref (output);
operation_shutdown (FALSE);
return;
}
qmi_message_pbm_get_all_capabilities_output_get_capability_basic_information (output, &capability_basic_information, NULL);
qmi_message_pbm_get_all_capabilities_output_get_group_capability (output, &group_capability, NULL);
qmi_message_pbm_get_all_capabilities_output_get_additional_number_capability (output, &additional_number_capability, NULL);
qmi_message_pbm_get_all_capabilities_output_get_email_capability (output, &email_capability, NULL);
qmi_message_pbm_get_all_capabilities_output_get_second_name_capability (output, &second_name_capability, NULL);
qmi_message_pbm_get_all_capabilities_output_get_hidden_records_capability (output, &hidden_records_capability, NULL);
qmi_message_pbm_get_all_capabilities_output_get_grouping_information_alpha_string_capability (output, &grouping_information_alpha_string_capability, NULL);
qmi_message_pbm_get_all_capabilities_output_get_additional_number_alpha_string_capability (output, &additional_number_alpha_string_capability, NULL);
g_print ("[%s] Phonebook capabilities:%s\n",
qmi_device_get_path_display (ctx->device),
(capability_basic_information ||
group_capability ||
additional_number_capability ||
email_capability ||
second_name_capability ||
hidden_records_capability ||
grouping_information_alpha_string_capability ||
additional_number_alpha_string_capability) ? "" : " none");
if (capability_basic_information) {
g_print ("Capability basic information:\n");
for (i = 0; i < capability_basic_information->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElement *session;
session = &g_array_index (capability_basic_information,
QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
for (j = 0; j < session->phonebooks->len; j++) {
QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElementPhonebooksElement *phonebook;
g_autofree gchar *phonebook_type_str = NULL;
phonebook = &g_array_index (session->phonebooks,
QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElementPhonebooksElement,
j);
phonebook_type_str = qmi_pbm_phonebook_type_build_string_from_mask (phonebook->phonebook_type);
g_print ("\t\t[%s]:\n", VALIDATE_MASK_NONE (phonebook_type_str));
g_print ("\t\t\tUsed records: %" G_GUINT16_FORMAT "\n", phonebook->used_records);
g_print ("\t\t\tMaximum records: %" G_GUINT16_FORMAT "\n", phonebook->maximum_records);
g_print ("\t\t\tMaximum number length: %u\n", phonebook->maximum_number_length);
g_print ("\t\t\tMaximum name length: %u\n", phonebook->maximum_name_length);
}
}
}
if (group_capability) {
g_print ("Group capability:\n");
for (i = 0; i < group_capability->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputGroupCapabilityElement *session;
session = &g_array_index (group_capability,
QmiMessagePbmGetAllCapabilitiesOutputGroupCapabilityElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
g_print ("\t\tMaximum groups: %u\n", session->maximum_groups);
g_print ("\t\tMaximum group tag length: %u\n", session->maximum_group_tag_length);
}
}
if (additional_number_capability) {
g_print ("Additional number capability:\n");
for (i = 0; i < additional_number_capability->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberCapabilityElement *session;
session = &g_array_index (additional_number_capability,
QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberCapabilityElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
g_print ("\t\tMaximum additional numbers: %u\n", session->maximum_additional_numbers);
g_print ("\t\tMaximum additional number length: %u\n", session->maximum_additional_number_length);
g_print ("\t\tMaximum additional number tag length: %u\n", session->maximum_additional_number_tag_length);
}
}
if (email_capability) {
g_print ("Email capability:\n");
for (i = 0; i < email_capability->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputEmailCapabilityElement *session;
session = &g_array_index (email_capability,
QmiMessagePbmGetAllCapabilitiesOutputEmailCapabilityElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
g_print ("\t\tMaximum emails: %u\n", session->maximum_emails);
g_print ("\t\tMaximum email address length: %u\n", session->maximum_email_address_length);
}
}
if (second_name_capability) {
g_print ("Second name capability:\n");
for (i = 0; i < second_name_capability->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputSecondNameCapabilityElement *session;
session = &g_array_index (second_name_capability,
QmiMessagePbmGetAllCapabilitiesOutputSecondNameCapabilityElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
g_print ("\t\tMaximum second name length: %u\n", session->maximum_second_name_length);
}
}
if (hidden_records_capability) {
g_print ("Hidden records capability:\n");
for (i = 0; i < hidden_records_capability->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputHiddenRecordsCapabilityElement *session;
session = &g_array_index (hidden_records_capability,
QmiMessagePbmGetAllCapabilitiesOutputHiddenRecordsCapabilityElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
g_print ("\t\tSupported: %s\n", session->supported ? "yes" : "no");
}
}
if (grouping_information_alpha_string_capability) {
g_print ("Alpha string capability:\n");
for (i = 0; i < grouping_information_alpha_string_capability->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputGroupingInformationAlphaStringCapabilityElement *session;
session = &g_array_index (grouping_information_alpha_string_capability,
QmiMessagePbmGetAllCapabilitiesOutputGroupingInformationAlphaStringCapabilityElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
g_print ("\t\tMaximum records: %u\n", session->maximum_records);
g_print ("\t\tUsed records: %u\n", session->used_records);
g_print ("\t\tMaximum string length: %u\n", session->maximum_string_length);
}
}
if (additional_number_alpha_string_capability) {
g_print ("Additional number alpha string capability:\n");
for (i = 0; i < additional_number_alpha_string_capability->len; i++) {
QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberAlphaStringCapabilityElement *session;
session = &g_array_index (additional_number_alpha_string_capability,
QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberAlphaStringCapabilityElement,
i);
g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type));
g_print ("\t\tMaximum records: %u\n", session->maximum_records);
g_print ("\t\tUsed records: %u\n", session->used_records);
g_print ("\t\tMaximum string length: %u\n", session->maximum_string_length);
}
}
qmi_message_pbm_get_all_capabilities_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_PBM_GET_ALL_CAPABILITIES */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_pbm_run (QmiDevice *device,
QmiClientPbm *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_PBM_GET_ALL_CAPABILITIES
if (get_all_capabilities_flag) {
g_debug ("Asynchronously getting phonebook capabilities...");
qmi_client_pbm_get_all_capabilities (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_all_capabilities_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_PBM */

File diff suppressed because it is too large Load Diff

View File

@ -1,193 +0,0 @@
/* -*- 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) 2021 Aleksander Morgado <aleksander@aleksander.es>
*/
#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 <libqmi-glib.h>
#include "qmicli.h"
#include "qmicli-helpers.h"
/* Options */
static gboolean get_wwan_iface_flag;
static gboolean get_expected_data_format_flag;
static gchar *set_expected_data_format_str;
static GOptionEntry entries[] = {
{ "get-wwan-iface", 'w', 0, G_OPTION_ARG_NONE, &get_wwan_iface_flag,
"Get the associated WWAN iface name",
NULL
},
{ "get-expected-data-format", 'e', 0, G_OPTION_ARG_NONE, &get_expected_data_format_flag,
"Get the expected data format in the WWAN iface",
NULL
},
{ "set-expected-data-format", 'E', 0, G_OPTION_ARG_STRING, &set_expected_data_format_str,
"Set the expected data format in the WWAN iface",
"[802-3|raw-ip|qmap-pass-through]"
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_qmiwwan_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("qmiwwan",
"qmi_wwan specific options:",
"Show qmi_wwan driver specific options", NULL, NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_qmiwwan_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (get_wwan_iface_flag +
get_expected_data_format_flag +
!!set_expected_data_format_str);
if (n_actions > 1) {
g_printerr ("error: too many qmi_wwan specific actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
/******************************************************************************/
static gboolean
device_set_expected_data_format_cb (QmiDevice *dev)
{
QmiDeviceExpectedDataFormat expected;
GError *error = NULL;
if (!qmicli_read_device_expected_data_format_from_string (set_expected_data_format_str, &expected) ||
expected == QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN)
g_printerr ("error: invalid requested data format: %s", set_expected_data_format_str);
else if (!qmi_device_set_expected_data_format (dev, expected, &error)) {
g_printerr ("error: cannot set expected data format: %s\n", error->message);
g_error_free (error);
} else
g_print ("[%s] expected data format set to: %s\n",
qmi_device_get_path_display (dev),
qmi_device_expected_data_format_get_string (expected));
/* We're done now */
qmicli_async_operation_done (!error, FALSE);
g_object_unref (dev);
return FALSE;
}
static void
device_set_expected_data_format (QmiDevice *dev)
{
g_debug ("Setting expected WWAN data format this control port...");
g_idle_add ((GSourceFunc) device_set_expected_data_format_cb, g_object_ref (dev));
}
static gboolean
device_get_expected_data_format_cb (QmiDevice *dev)
{
QmiDeviceExpectedDataFormat expected;
GError *error = NULL;
expected = qmi_device_get_expected_data_format (dev, &error);
if (expected == QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN) {
g_printerr ("error: cannot get expected data format: %s\n", error->message);
g_error_free (error);
} else
g_print ("%s\n", qmi_device_expected_data_format_get_string (expected));
/* We're done now */
qmicli_async_operation_done (!error, FALSE);
g_object_unref (dev);
return FALSE;
}
static void
device_get_expected_data_format (QmiDevice *dev)
{
g_debug ("Getting expected WWAN data format this control port...");
g_idle_add ((GSourceFunc) device_get_expected_data_format_cb, g_object_ref (dev));
}
static gboolean
device_get_wwan_iface_cb (QmiDevice *dev)
{
const gchar *wwan_iface;
wwan_iface = qmi_device_get_wwan_iface (dev);
if (!wwan_iface)
g_printerr ("error: cannot get WWAN interface name\n");
else
g_print ("%s\n", wwan_iface);
/* We're done now */
qmicli_async_operation_done (!!wwan_iface, FALSE);
g_object_unref (dev);
return FALSE;
}
static void
device_get_wwan_iface (QmiDevice *dev)
{
g_debug ("Getting WWAN iface for this control port...");
g_idle_add ((GSourceFunc) device_get_wwan_iface_cb, g_object_ref (dev));
}
/******************************************************************************/
/* Common */
void
qmicli_qmiwwan_run (QmiDevice *device,
GCancellable *cancellable)
{
if (get_wwan_iface_flag)
device_get_wwan_iface (device);
else if (get_expected_data_format_flag)
device_get_expected_data_format (device);
else if (set_expected_data_format_str)
device_set_expected_data_format (device);
else
g_warn_if_reached ();
}

View File

@ -1,430 +0,0 @@
/* -*- 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 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"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_QOS
#undef VALIDATE_UNKNOWN
#define VALIDATE_UNKNOWN(str) (str ? str : "unknown")
/* Context */
typedef struct {
QmiDevice *device;
QmiClientQos *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gint get_flow_status_int = -1;
static gboolean get_network_status_flag;
static gint swi_read_data_stats_int = -1;
static gboolean reset_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_QOS_GET_FLOW_STATUS
{ "qos-get-flow-status", 0, 0, G_OPTION_ARG_INT, &get_flow_status_int,
"Get QoS flow status",
"[QoS ID]"
},
#endif
#if defined HAVE_QMI_MESSAGE_QOS_GET_NETWORK_STATUS
{ "qos-get-network-status", 0, 0, G_OPTION_ARG_NONE, &get_network_status_flag,
"Gets the network status",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_QOS_SWI_READ_DATA_STATS
{ "qos-swi-read-data-stats", 0, 0, G_OPTION_ARG_INT, &swi_read_data_stats_int,
"Read data stats (Sierra Wireless specific)",
"[APN ID]"
},
#endif
#if defined HAVE_QMI_MESSAGE_QOS_RESET
{ "qos-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag,
"Reset the service state",
NULL
},
#endif
{ "qos-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a QOS client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_qos_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("qos",
"QoS options:",
"Show Quality of Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_qos_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = ((get_flow_status_int >= 0) +
get_network_status_flag +
(swi_read_data_stats_int >= 0) +
reset_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many QoS actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->cancellable)
g_object_unref (context->cancellable);
if (context->device)
g_object_unref (context->device);
if (context->client)
g_object_unref (context->client);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_QOS_GET_FLOW_STATUS
static void
get_flow_status_ready (QmiClientQos *client,
GAsyncResult *res)
{
QmiMessageQosGetFlowStatusOutput *output;
GError *error = NULL;
QmiQosStatus flow_status;
output = qmi_client_qos_get_flow_status_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_qos_get_flow_status_output_get_result (output, &error)) {
g_printerr ("error: couldn't get QoS flow status: %s\n", error->message);
g_error_free (error);
qmi_message_qos_get_flow_status_output_unref (output);
operation_shutdown (FALSE);
return;
}
qmi_message_qos_get_flow_status_output_get_value (output, &flow_status, NULL);
g_print ("[%s] QoS flow status: %s\n",
qmi_device_get_path_display (ctx->device),
qmi_qos_status_get_string (flow_status));
qmi_message_qos_get_flow_status_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_QOS_GET_FLOW_STATUS */
#if defined HAVE_QMI_MESSAGE_QOS_GET_NETWORK_STATUS
static void
get_network_status_ready (QmiClientQos *client,
GAsyncResult *res)
{
QmiMessageQosGetNetworkStatusOutput *output;
GError *error = NULL;
gboolean qos_supported;
output = qmi_client_qos_get_network_status_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_qos_get_network_status_output_get_result (output, &error)) {
g_printerr ("error: couldn't get network status: %s\n", error->message);
g_error_free (error);
qmi_message_qos_get_network_status_output_unref (output);
operation_shutdown (FALSE);
return;
}
qmi_message_qos_get_network_status_output_get_qos_supported (output, &qos_supported, NULL);
g_print ("[%s] QoS %ssupported in network\n",
qmi_device_get_path_display (ctx->device),
qos_supported ? "" : "not ");
qmi_message_qos_get_network_status_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_QOS_GET_NETWORK_STATUS */
#if defined HAVE_QMI_MESSAGE_QOS_SWI_READ_DATA_STATS
static void
swi_read_data_stats_ready (QmiClientQos *client,
GAsyncResult *res)
{
QmiMessageQosSwiReadDataStatsOutput *output;
GError *error = NULL;
guint32 apn_id = 0;
guint32 apn_tx_packets = 0;
guint32 apn_tx_packets_dropped = 0;
guint32 apn_rx_packets = 0;
guint64 apn_tx_bytes = 0;
guint64 apn_tx_bytes_dropped = 0;
guint64 apn_rx_bytes = 0;
GArray *flow = NULL;
output = qmi_client_qos_swi_read_data_stats_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_qos_swi_read_data_stats_output_get_result (output, &error)) {
g_printerr ("error: couldn't read data stats: %s\n", error->message);
g_error_free (error);
qmi_message_qos_swi_read_data_stats_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] QoS data stats read\n",
qmi_device_get_path_display (ctx->device));
if (qmi_message_qos_swi_read_data_stats_output_get_apn (
output,
&apn_id,
&apn_tx_packets,
&apn_tx_packets_dropped,
&apn_rx_packets,
&apn_tx_bytes,
&apn_tx_bytes_dropped,
&apn_rx_bytes,
NULL)) {
g_print (" APN ID: %u\n", apn_id);
g_print (" TX packets: %u\n", apn_tx_packets);
g_print (" TX packets dropped: %u\n", apn_tx_packets_dropped);
g_print (" RX packets: %u\n", apn_rx_packets);
g_print (" TX bytes: %" G_GUINT64_FORMAT "\n", apn_tx_bytes);
g_print (" TX bytes dropped: %" G_GUINT64_FORMAT "\n", apn_tx_bytes_dropped);
g_print (" RX bytes: %" G_GUINT64_FORMAT "\n", apn_rx_bytes);
}
if (qmi_message_qos_swi_read_data_stats_output_get_flow (
output,
&flow,
NULL)) {
guint i;
for (i = 0; i < flow->len; i++) {
QmiMessageQosSwiReadDataStatsOutputFlowElement *element;
element = &g_array_index(flow, QmiMessageQosSwiReadDataStatsOutputFlowElement, i);
g_print (" Flow %u\n", i);
g_print (" Bearer ID: %u\n", element->bearer_id);
g_print (" TX packets: %u\n", element->tx_packets);
g_print (" TX packets dropped: %u\n", element->tx_packets_dropped);
g_print (" TX bytes: %" G_GUINT64_FORMAT "\n", element->tx_bytes);
g_print (" TX bytes dropped: %" G_GUINT64_FORMAT "\n", element->tx_bytes_dropped);
}
}
qmi_message_qos_swi_read_data_stats_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_QOS_SWI_READ_DATA_STATS */
#if defined HAVE_QMI_MESSAGE_QOS_RESET
static void
reset_ready (QmiClientQos *client,
GAsyncResult *res)
{
QmiMessageQosResetOutput *output;
GError *error = NULL;
output = qmi_client_qos_reset_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_qos_reset_output_get_result (output, &error)) {
g_printerr ("error: couldn't reset the QoS service: %s\n", error->message);
g_error_free (error);
qmi_message_qos_reset_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully performed QoS service reset\n",
qmi_device_get_path_display (ctx->device));
qmi_message_qos_reset_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_QOS_RESET */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_qos_run (QmiDevice *device,
QmiClientQos *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_QOS_GET_FLOW_STATUS
if (get_flow_status_int >= 0) {
QmiMessageQosGetFlowStatusInput *input;
input = qmi_message_qos_get_flow_status_input_new ();
qmi_message_qos_get_flow_status_input_set_qos_id (input, get_flow_status_int, NULL);
g_debug ("Asynchronously getting QoS flow status...");
qmi_client_qos_get_flow_status (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_flow_status_ready,
NULL);
qmi_message_qos_get_flow_status_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_QOS_GET_NETWORK_STATUS
if (get_network_status_flag) {
g_debug ("Asynchronously getting network status...");
qmi_client_qos_get_network_status (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_network_status_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_QOS_SWI_READ_DATA_STATS
if (swi_read_data_stats_int >= 0) {
QmiMessageQosSwiReadDataStatsInput *input;
input = qmi_message_qos_swi_read_data_stats_input_new ();
qmi_message_qos_swi_read_data_stats_input_set_apn_id (input, swi_read_data_stats_int, NULL);
g_debug ("Asynchronously reading data stats...");
qmi_client_qos_swi_read_data_stats (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)swi_read_data_stats_ready,
NULL);
qmi_message_qos_swi_read_data_stats_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_QOS_RESET
if (reset_flag) {
g_debug ("Asynchronously resetting QoS service...");
qmi_client_qos_reset (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)reset_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_QOS */

View File

@ -1,295 +0,0 @@
/* -*- 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) 2020 Google Inc.
*/
#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"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_SAR
/* Context */
typedef struct {
QmiDevice *device;
QmiClientSar *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gchar *rf_set_state_str;
static gboolean rf_get_state_flag;
static gboolean noop_flag;
#undef VALIDATE_UNKNOWN
#define VALIDATE_UNKNOWN(str) (str ? str : "unknown")
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_SAR_RF_GET_STATE
{ "sar-rf-get-state", 0, 0, G_OPTION_ARG_NONE, &rf_get_state_flag,
"Get RF state",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_SAR_RF_SET_STATE
{ "sar-rf-set-state", 0, 0, G_OPTION_ARG_STRING, &rf_set_state_str,
"Set RF state.",
"[(state number)]"
},
#endif
{ "sar-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a SAR client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_sar_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("sar",
"SAR options:",
"Show Specific Absorption Rate options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_sar_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (!!rf_set_state_str +
rf_get_state_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many SAR actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->client)
g_object_unref (context->client);
g_object_unref (context->cancellable);
g_object_unref (context->device);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_SAR_RF_GET_STATE
static void
rf_get_state_ready (QmiClientSar *client,
GAsyncResult *res)
{
QmiMessageSarRfGetStateOutput *output;
GError *error = NULL;
QmiSarRfState rf_state;
output = qmi_client_sar_rf_get_state_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_sar_rf_get_state_output_get_result (output, &error)) {
g_printerr ("error: couldn't get SAR RF state: %s\n", error->message);
g_error_free (error);
qmi_message_sar_rf_get_state_output_unref (output);
operation_shutdown (FALSE);
return;
}
qmi_message_sar_rf_get_state_output_get_state (output, &rf_state, NULL);
g_print ("[%s] Successfully got SAR RF state: %s\n",
qmi_device_get_path_display (ctx->device),
qmi_sar_rf_state_get_string (rf_state));
qmi_message_sar_rf_get_state_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_SAR_RF_GET_STATE */
#if defined HAVE_QMI_MESSAGE_SAR_RF_SET_STATE
static QmiMessageSarRfSetStateInput *
rf_set_state_input_create (const gchar *str)
{
QmiMessageSarRfSetStateInput *input = NULL;
QmiSarRfState rf_state;
if (qmicli_read_sar_rf_state_from_string (str, &rf_state)) {
GError *error = NULL;
input = qmi_message_sar_rf_set_state_input_new ();
if (!qmi_message_sar_rf_set_state_input_set_state (
input,
rf_state,
&error)) {
g_printerr ("error: couldn't create input data: '%s'\n",
error->message);
g_error_free (error);
qmi_message_sar_rf_set_state_input_unref (input);
input = NULL;
}
}
return input;
}
static void
rf_set_state_ready (QmiClientSar *client,
GAsyncResult *res)
{
QmiMessageSarRfSetStateOutput *output;
GError *error = NULL;
output = qmi_client_sar_rf_set_state_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_sar_rf_set_state_output_get_result (output, &error)) {
g_printerr ("error: couldn't set RF state: %s\n", error->message);
g_error_free (error);
qmi_message_sar_rf_set_state_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] RF state set successfully\n",
qmi_device_get_path_display (ctx->device));
qmi_message_sar_rf_set_state_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_SAR_RF_SET_STATE */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_sar_run (QmiDevice *device,
QmiClientSar *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);
#if defined HAVE_QMI_MESSAGE_SAR_RF_GET_STATE
if (rf_get_state_flag) {
g_debug ("Asynchronously getting RF power state...");
qmi_client_sar_rf_get_state (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback) rf_get_state_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_SAR_RF_SET_STATE
if (rf_set_state_str) {
QmiMessageSarRfSetStateInput *input;
g_debug ("Asynchronously setting RF power state...");
input = rf_set_state_input_create (rf_set_state_str);
if (!input) {
operation_shutdown (FALSE);
return;
}
qmi_client_sar_rf_set_state (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback) rf_set_state_ready,
NULL);
qmi_message_sar_rf_set_state_input_unref (input);
return;
}
#endif /* HAVE_QMI_MESSAGE_SAR_RF_SET_STATE */
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_SAR */

File diff suppressed because it is too large Load Diff

View File

@ -1,379 +0,0 @@
/* -*- 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) 2014-2017 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"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_VOICE
#undef VALIDATE_MASK_NONE
#define VALIDATE_MASK_NONE(str) (str ? str : "none")
/* Context */
typedef struct {
QmiDevice *device;
QmiClientVoice *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gboolean get_config_flag;
static gboolean get_supported_messages_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_VOICE_GET_CONFIG
{ "voice-get-config", 0, 0, G_OPTION_ARG_NONE, &get_config_flag,
"Get Voice service configuration",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_VOICE_GET_SUPPORTED_MESSAGES
{ "voice-get-supported-messages", 0, 0, G_OPTION_ARG_NONE, &get_supported_messages_flag,
"Get supported messages",
NULL
},
#endif
{ "voice-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a VOICE client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_voice_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("voice",
"VOICE options:",
"Show Voice Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_voice_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (get_config_flag +
get_supported_messages_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many VOICE actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->client)
g_object_unref (context->client);
g_object_unref (context->cancellable);
g_object_unref (context->device);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_VOICE_GET_CONFIG
static void
get_config_ready (QmiClientVoice *client,
GAsyncResult *res)
{
QmiMessageVoiceGetConfigOutput *output;
GError *error = NULL;
QmiVoiceDomain current_voice_domain_preference;
QmiVoicePrivacy current_voice_privacy_preference;
gboolean current_amr_status_gsm;
QmiVoiceWcdmaAmrStatus current_amr_status_wcdma;
guint8 current_preferred_voice_so_nam_id;
gboolean current_preferred_voice_so_evrc_capability;
QmiVoiceServiceOption current_preferred_voice_so_home_page_voice_service_option;
QmiVoiceServiceOption current_preferred_voice_so_home_origination_voice_service_option;
QmiVoiceServiceOption current_preferred_voice_so_roaming_origination_voice_service_option;
QmiVoiceTtyMode current_tty_mode;
guint8 roam_timer_count_nam_id;
guint32 roam_timer_count_roam_timer;
guint8 air_timer_count_nam_id;
guint32 air_timer_count_air_timer;
gboolean auto_answer_status;
output = qmi_client_voice_get_config_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_voice_get_config_output_get_result (output, &error)) {
g_printerr ("error: couldn't get Voice configuration: %s\n", error->message);
g_error_free (error);
qmi_message_voice_get_config_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully retrieved Voice configuration:\n",
qmi_device_get_path_display (ctx->device));
if (qmi_message_voice_get_config_output_get_auto_answer_status (
output,
&auto_answer_status,
NULL))
g_print ("Auto Answer Status: '%s'",
auto_answer_status ? "enabled" : "disabled");
if (qmi_message_voice_get_config_output_get_air_timer_count (
output,
&air_timer_count_nam_id,
&air_timer_count_air_timer,
NULL))
g_print ("Air Timer Count:\n"
"\tNAM ID: '%u'"
"\tTimer: '%u'",
air_timer_count_nam_id,
air_timer_count_air_timer);
if (qmi_message_voice_get_config_output_get_roam_timer_count (
output,
&roam_timer_count_nam_id,
&roam_timer_count_roam_timer,
NULL))
g_print ("Roam Timer Count:\n"
"\tNAM ID: '%u'"
"\tTimer: '%u'",
roam_timer_count_nam_id,
roam_timer_count_roam_timer);
if (qmi_message_voice_get_config_output_get_current_tty_mode (
output,
&current_tty_mode,
NULL))
g_print ("Current TTY mode: '%s'",
qmi_voice_tty_mode_get_string (current_tty_mode));
if (qmi_message_voice_get_config_output_get_current_preferred_voice_so (
output,
&current_preferred_voice_so_nam_id,
&current_preferred_voice_so_evrc_capability,
&current_preferred_voice_so_home_page_voice_service_option,
&current_preferred_voice_so_home_origination_voice_service_option,
&current_preferred_voice_so_roaming_origination_voice_service_option,
NULL)) {
g_print ("Current Preferred Voice SO:\n"
"\tNAM ID: '%u'\n"
"\tEVRC capability: '%s'\n"
"\tHome Page Voice SO: '%s'\n"
"\tHome Origination Voice SO: '%s'\n"
"\tRoaming Origination Voice SO: '%s'\n",
current_preferred_voice_so_nam_id,
current_preferred_voice_so_evrc_capability ? "enabled" : "disabled",
qmi_voice_service_option_get_string (current_preferred_voice_so_home_page_voice_service_option),
qmi_voice_service_option_get_string (current_preferred_voice_so_home_origination_voice_service_option),
qmi_voice_service_option_get_string (current_preferred_voice_so_roaming_origination_voice_service_option));
}
if (qmi_message_voice_get_config_output_get_current_amr_status (
output,
&current_amr_status_gsm, &current_amr_status_wcdma,
NULL)) {
gchar *current_amr_status_wcdma_str;
current_amr_status_wcdma_str = qmi_voice_wcdma_amr_status_build_string_from_mask (current_amr_status_wcdma);
g_print ("AMR Status:\n"
"\tGSM: '%s'\n"
"\tWCDMA: '%s' (0x%04X)\n",
current_amr_status_gsm ? "enabled" : "disabled",
VALIDATE_MASK_NONE (current_amr_status_wcdma_str),
current_amr_status_wcdma);
g_free (current_amr_status_wcdma_str);
}
if (qmi_message_voice_get_config_output_get_current_voice_privacy_preference (
output,
&current_voice_privacy_preference,
NULL))
g_print ("Current Voice Privacy Preference: '%s'\n",
qmi_voice_privacy_get_string (current_voice_privacy_preference));
if (qmi_message_voice_get_config_output_get_current_voice_domain_preference (
output,
&current_voice_domain_preference,
NULL))
g_print ("Current Voice Domain Preference: '%s'\n",
qmi_voice_domain_get_string (current_voice_domain_preference));
qmi_message_voice_get_config_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_VOICE_GET_CONFIG */
#if defined HAVE_QMI_MESSAGE_VOICE_GET_SUPPORTED_MESSAGES
static void
get_supported_messages_ready (QmiClientVoice *client,
GAsyncResult *res)
{
QmiMessageVoiceGetSupportedMessagesOutput *output;
GError *error = NULL;
GArray *bytearray = NULL;
gchar *str;
output = qmi_client_voice_get_supported_messages_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_voice_get_supported_messages_output_get_result (output, &error)) {
g_printerr ("error: couldn't get supported VOICE messages: %s\n", error->message);
g_error_free (error);
qmi_message_voice_get_supported_messages_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully got supported VOICE messages:\n",
qmi_device_get_path_display (ctx->device));
qmi_message_voice_get_supported_messages_output_get_list (output, &bytearray, NULL);
str = qmicli_get_supported_messages_list (bytearray ? (const guint8 *)bytearray->data : NULL,
bytearray ? bytearray->len : 0);
g_print ("%s", str);
g_free (str);
qmi_message_voice_get_supported_messages_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_VOICE_GET_SUPPORTED_MESSAGES */
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_voice_run (QmiDevice *device,
QmiClientVoice *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_VOICE_GET_CONFIG
if (get_config_flag) {
QmiMessageVoiceGetConfigInput *input;
input = qmi_message_voice_get_config_input_new ();
qmi_message_voice_get_config_input_set_auto_answer (input, TRUE, NULL);
qmi_message_voice_get_config_input_set_air_timer (input, TRUE, NULL);
qmi_message_voice_get_config_input_set_roam_timer (input, TRUE, NULL);
qmi_message_voice_get_config_input_set_tty_mode (input, TRUE, NULL);
qmi_message_voice_get_config_input_set_preferred_voice_service_option (input, TRUE, NULL);
qmi_message_voice_get_config_input_set_amr_status (input, TRUE, NULL);
qmi_message_voice_get_config_input_set_preferred_voice_privacy (input, TRUE, NULL);
if (qmi_client_check_version (QMI_CLIENT (ctx->client), 2, 3))
qmi_message_voice_get_config_input_set_nam_index (input, TRUE, NULL);
if (qmi_client_check_version (QMI_CLIENT (ctx->client), 2, 9))
qmi_message_voice_get_config_input_set_voice_domain_preference (input, TRUE, NULL);
g_debug ("Asynchronously getting voice configuration...");
qmi_client_voice_get_config (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_config_ready,
NULL);
qmi_message_voice_get_config_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_VOICE_GET_SUPPORTED_MESSAGES
if (get_supported_messages_flag) {
g_debug ("Asynchronously getting supported voice messages...");
qmi_client_voice_get_supported_messages (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_supported_messages_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_VOICE */

View File

@ -1,811 +0,0 @@
/* -*- 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) 2014-2017 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"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_WDA
#define QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAMS_UNDEFINED 0xFFFFFFFF
#define QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAM_SIZE_UNDEFINED 0xFFFFFFFF
#define QMI_WDA_ENDPOINT_INTERFACE_NUMBER_UNDEFINED -1
/* Context */
typedef struct {
QmiDevice *device;
QmiClientWda *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gchar *set_data_format_str;
static gchar *get_data_format_str;
static gboolean get_data_format_flag;
static gboolean get_supported_messages_flag;
static gboolean noop_flag;
#if defined HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT
static gboolean
parse_get_data_format (const gchar *option_name,
const gchar *value,
gpointer data,
GError **error)
{
get_data_format_flag = TRUE;
if (value && value[0])
get_data_format_str = g_strdup (value);
return TRUE;
}
#endif
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_WDA_SET_DATA_FORMAT
{ "wda-set-data-format", 0, 0, G_OPTION_ARG_STRING, &set_data_format_str,
"Set data format (allowed keys: link-layer-protocol (802-3|raw-ip), ul-protocol (disabled|tlp|qc-ncm|mbim|rndis|qmap|qmapv5), dl-protocol (disabled|tlp|qc-ncm|mbim|rndis|qmap|qmapv5), dl-datagram-max-size, dl-max-datagrams, ep-type (undefined|hsusb|pcie|embedded), ep-iface-number, ul-datagram-max-size, ul-max-datagrams)",
"[\"key=value,...\"]"
},
#endif
#if defined HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT
{ "wda-get-data-format", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, parse_get_data_format,
"Get data format (allowed keys: ep-type (undefined|hsusb|pcie|embedded), ep-iface-number); also allows empty key list",
"[\"key=value,...\"]"
},
#endif
#if defined HAVE_QMI_MESSAGE_WDA_GET_SUPPORTED_MESSAGES
{ "wda-get-supported-messages", 0, 0, G_OPTION_ARG_NONE, &get_supported_messages_flag,
"Get supported messages",
NULL
},
#endif
{ "wda-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a WDA client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_wda_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("wda",
"WDA options:",
"Show Wireless Data Administrative options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_wda_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (!!set_data_format_str +
get_data_format_flag +
get_supported_messages_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many WDA actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->client)
g_object_unref (context->client);
g_object_unref (context->cancellable);
g_object_unref (context->device);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
#if defined HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT
typedef struct {
QmiDataEndpointType endpoint_type;
gint endpoint_iface_number;
} GetDataFormatProperties;
static gboolean
get_data_format_properties_handle (const gchar *key,
const gchar *value,
GError **error,
gpointer user_data)
{
GetDataFormatProperties *props = (GetDataFormatProperties *)user_data;
if (!value || !value[0]) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"key '%s' requires a value",
key);
return FALSE;
}
if (g_ascii_strcasecmp (key, "ep-type") == 0) {
if (!qmicli_read_data_endpoint_type_from_string (value, &(props->endpoint_type))) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"Unrecognized Endpoint Type '%s'",
value);
return FALSE;
}
return TRUE;
}
if (g_ascii_strcasecmp (key, "ep-iface-number") == 0) {
props->endpoint_iface_number = atoi (value);
return TRUE;
}
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"Unrecognized option '%s'",
key);
return FALSE;
}
static QmiMessageWdaGetDataFormatInput *
get_data_format_input_create (const gchar *str)
{
g_autoptr(QmiMessageWdaGetDataFormatInput) input = NULL;
g_autoptr(GError) error = NULL;
GetDataFormatProperties props = {
.endpoint_type = QMI_DATA_ENDPOINT_TYPE_UNDEFINED,
.endpoint_iface_number = QMI_WDA_ENDPOINT_INTERFACE_NUMBER_UNDEFINED,
};
input = qmi_message_wda_get_data_format_input_new ();
if (!qmicli_parse_key_value_string (str,
&error,
get_data_format_properties_handle,
&props)) {
g_printerr ("error: could not parse input string '%s'\n", error->message);
return NULL;
}
if ((props.endpoint_type == QMI_DATA_ENDPOINT_TYPE_UNDEFINED) ^
(props.endpoint_iface_number == QMI_WDA_ENDPOINT_INTERFACE_NUMBER_UNDEFINED)) {
g_printerr ("error: endpoint type and interface number must be both set or both unset\n");
return NULL;
}
if ((props.endpoint_type != QMI_DATA_ENDPOINT_TYPE_UNDEFINED) &&
(props.endpoint_iface_number != QMI_WDA_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) &&
!qmi_message_wda_get_data_format_input_set_endpoint_info (
input,
props.endpoint_type,
props.endpoint_iface_number,
&error)) {
g_printerr ("error: could not set peripheral endpoint id: %s\n", error->message);
return NULL;
}
return g_steal_pointer (&input);
}
static void
get_data_format_ready (QmiClientWda *client,
GAsyncResult *res)
{
QmiMessageWdaGetDataFormatOutput *output;
GError *error = NULL;
gboolean qos_format;
QmiWdaLinkLayerProtocol link_layer_protocol;
QmiWdaDataAggregationProtocol data_aggregation_protocol;
guint32 ndp_signature;
guint32 data_aggregation_max_size;
guint32 data_aggregation_max_datagrams;
output = qmi_client_wda_get_data_format_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_wda_get_data_format_output_get_result (output, &error)) {
g_printerr ("error: couldn't get data format: %s\n", error->message);
g_error_free (error);
qmi_message_wda_get_data_format_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully got data format\n",
qmi_device_get_path_display (ctx->device));
if (qmi_message_wda_get_data_format_output_get_qos_format (
output,
&qos_format,
NULL))
g_print (" QoS flow header: %s\n", qos_format ? "yes" : "no");
if (qmi_message_wda_get_data_format_output_get_link_layer_protocol (
output,
&link_layer_protocol,
NULL))
g_print (" Link layer protocol: '%s'\n",
qmi_wda_link_layer_protocol_get_string (link_layer_protocol));
if (qmi_message_wda_get_data_format_output_get_uplink_data_aggregation_protocol (
output,
&data_aggregation_protocol,
NULL))
g_print (" Uplink data aggregation protocol: '%s'\n",
qmi_wda_data_aggregation_protocol_get_string (data_aggregation_protocol));
if (qmi_message_wda_get_data_format_output_get_downlink_data_aggregation_protocol (
output,
&data_aggregation_protocol,
NULL))
g_print ("Downlink data aggregation protocol: '%s'\n",
qmi_wda_data_aggregation_protocol_get_string (data_aggregation_protocol));
if (qmi_message_wda_get_data_format_output_get_ndp_signature (
output,
&ndp_signature,
NULL))
g_print (" NDP signature: '%u'\n", ndp_signature);
if (qmi_message_wda_get_data_format_output_get_downlink_data_aggregation_max_datagrams (
output,
&data_aggregation_max_datagrams,
NULL))
g_print ("Downlink data aggregation max datagrams: '%u'\n", data_aggregation_max_datagrams);
if (qmi_message_wda_get_data_format_output_get_downlink_data_aggregation_max_size (
output,
&data_aggregation_max_size,
NULL))
g_print ("Downlink data aggregation max size: '%u'\n", data_aggregation_max_size);
qmi_message_wda_get_data_format_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT */
#if defined HAVE_QMI_MESSAGE_WDA_SET_DATA_FORMAT
static void
set_data_format_ready (QmiClientWda *client,
GAsyncResult *res)
{
QmiMessageWdaSetDataFormatOutput *output;
GError *error = NULL;
gboolean qos_format;
QmiWdaLinkLayerProtocol link_layer_protocol;
QmiWdaDataAggregationProtocol data_aggregation_protocol;
guint32 ndp_signature;
guint32 dl_data_aggregation_max_datagrams;
guint32 dl_data_aggregation_max_size;
guint32 ul_data_aggregation_max_datagrams;
guint32 ul_data_aggregation_max_size;
output = qmi_client_wda_set_data_format_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_wda_set_data_format_output_get_result (output, &error)) {
g_printerr ("error: couldn't set data format: %s\n", error->message);
g_error_free (error);
qmi_message_wda_set_data_format_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully set data format\n",
qmi_device_get_path_display (ctx->device));
if (qmi_message_wda_set_data_format_output_get_qos_format (
output,
&qos_format,
NULL))
g_print (" QoS flow header: %s\n", qos_format ? "yes" : "no");
if (qmi_message_wda_set_data_format_output_get_link_layer_protocol (
output,
&link_layer_protocol,
NULL))
g_print (" Link layer protocol: '%s'\n",
qmi_wda_link_layer_protocol_get_string (link_layer_protocol));
if (qmi_message_wda_set_data_format_output_get_uplink_data_aggregation_protocol (
output,
&data_aggregation_protocol,
NULL))
g_print (" Uplink data aggregation protocol: '%s'\n",
qmi_wda_data_aggregation_protocol_get_string (data_aggregation_protocol));
if (qmi_message_wda_set_data_format_output_get_downlink_data_aggregation_protocol (
output,
&data_aggregation_protocol,
NULL))
g_print (" Downlink data aggregation protocol: '%s'\n",
qmi_wda_data_aggregation_protocol_get_string (data_aggregation_protocol));
if (qmi_message_wda_set_data_format_output_get_ndp_signature (
output,
&ndp_signature,
NULL))
g_print (" NDP signature: '%u'\n", ndp_signature);
if (qmi_message_wda_set_data_format_output_get_downlink_data_aggregation_max_datagrams (
output,
&dl_data_aggregation_max_datagrams,
NULL))
g_print ("Downlink data aggregation max datagrams: '%u'\n", dl_data_aggregation_max_datagrams);
if (qmi_message_wda_set_data_format_output_get_downlink_data_aggregation_max_size (
output,
&dl_data_aggregation_max_size,
NULL))
g_print (" Downlink data aggregation max size: '%u'\n", dl_data_aggregation_max_size);
if (qmi_message_wda_set_data_format_output_get_uplink_data_aggregation_max_datagrams (
output,
&ul_data_aggregation_max_datagrams,
NULL))
g_print (" Uplink data aggregation max datagrams: '%u'\n", ul_data_aggregation_max_datagrams);
if (qmi_message_wda_set_data_format_output_get_uplink_data_aggregation_max_size (
output,
&ul_data_aggregation_max_size,
NULL))
g_print (" Uplink data aggregation max size: '%u'\n", ul_data_aggregation_max_size);
qmi_message_wda_set_data_format_output_unref (output);
operation_shutdown (TRUE);
}
typedef struct {
QmiWdaLinkLayerProtocol link_layer_protocol;
QmiWdaDataAggregationProtocol ul_protocol;
QmiWdaDataAggregationProtocol dl_protocol;
guint32 dl_datagram_max_size;
guint32 dl_max_datagrams;
QmiDataEndpointType endpoint_type;
gint endpoint_iface_number;
guint32 ul_datagram_max_size;
guint32 ul_max_datagrams;
} SetDataFormatProperties;
static gboolean
set_data_format_properties_handle (const gchar *key,
const gchar *value,
GError **error,
gpointer user_data)
{
SetDataFormatProperties *props = (SetDataFormatProperties *)user_data;
if (!value || !value[0]) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"key '%s' requires a value",
key);
return FALSE;
}
if (g_ascii_strcasecmp (key, "link-layer-protocol") == 0) {
if (!qmicli_read_wda_link_layer_protocol_from_string (value, &(props->link_layer_protocol))) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"Unrecognized Link Layer Protocol '%s'",
value);
return FALSE;
}
return TRUE;
}
if (g_ascii_strcasecmp (key, "ul-protocol") == 0) {
if (!qmicli_read_wda_data_aggregation_protocol_from_string (value, &(props->ul_protocol))) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"Unrecognized Data Aggregation Protocol '%s'",
value);
return FALSE;
}
return TRUE;
}
if (g_ascii_strcasecmp (key, "dl-protocol") == 0) {
if (!qmicli_read_wda_data_aggregation_protocol_from_string (value, &(props->dl_protocol))) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"Unrecognized Data Aggregation Protocol '%s'",
value);
return FALSE;
}
return TRUE;
}
if (g_ascii_strcasecmp (key, "dl-datagram-max-size") == 0) {
props->dl_datagram_max_size = atoi(value);
return TRUE;
}
if (g_ascii_strcasecmp (key, "dl-max-datagrams") == 0) {
props->dl_max_datagrams = atoi(value);
return TRUE;
}
if (g_ascii_strcasecmp (key, "ep-type") == 0) {
if (!qmicli_read_data_endpoint_type_from_string (value, &(props->endpoint_type))) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"Unrecognized Endpoint Type '%s'",
value);
return FALSE;
}
return TRUE;
}
if (g_ascii_strcasecmp (key, "ep-iface-number") == 0) {
props->endpoint_iface_number = atoi(value);
return TRUE;
}
if (g_ascii_strcasecmp (key, "ul-datagram-max-size") == 0) {
props->ul_datagram_max_size = atoi(value);
return TRUE;
}
if (g_ascii_strcasecmp (key, "ul-max-datagrams") == 0) {
props->ul_max_datagrams = atoi(value);
return TRUE;
}
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"Unrecognized option '%s'",
key);
return FALSE;
}
static QmiMessageWdaSetDataFormatInput *
set_data_format_input_create (const gchar *str)
{
QmiMessageWdaSetDataFormatInput *input = NULL;
GError *error = NULL;
SetDataFormatProperties props = {
.link_layer_protocol = QMI_WDA_LINK_LAYER_PROTOCOL_UNKNOWN,
.ul_protocol = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED,
.dl_protocol = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED,
.dl_datagram_max_size = QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAM_SIZE_UNDEFINED,
.dl_max_datagrams = QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAMS_UNDEFINED,
.endpoint_type = QMI_DATA_ENDPOINT_TYPE_UNDEFINED,
.endpoint_iface_number = QMI_WDA_ENDPOINT_INTERFACE_NUMBER_UNDEFINED,
.ul_datagram_max_size = QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAM_SIZE_UNDEFINED,
.ul_max_datagrams = QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAMS_UNDEFINED,
};
input = qmi_message_wda_set_data_format_input_new ();
/* New key=value format */
if (strchr (str, '=')) {
if (!qmicli_parse_key_value_string (str,
&error,
set_data_format_properties_handle,
&props)) {
g_printerr ("error: could not parse input string '%s'\n", error->message);
g_error_free (error);
goto error_out;
}
if (!qmi_message_wda_set_data_format_input_set_uplink_data_aggregation_protocol (
input,
props.ul_protocol,
&error)) {
g_printerr ("error: could not set Upload data aggregation protocol '%d': %s\n",
props.ul_protocol, error->message);
g_error_free (error);
goto error_out;
}
if (!qmi_message_wda_set_data_format_input_set_downlink_data_aggregation_protocol (
input,
props.dl_protocol,
&error)) {
g_printerr ("error: could not set Download data aggregation protocol '%d': %s\n",
props.dl_protocol, error->message);
g_error_free (error);
goto error_out;
}
if (props.dl_datagram_max_size != QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAM_SIZE_UNDEFINED &&
!qmi_message_wda_set_data_format_input_set_downlink_data_aggregation_max_size (
input,
props.dl_datagram_max_size,
&error)) {
g_printerr ("error: could not set Download data aggregation max size %d: %s\n",
props.dl_datagram_max_size, error->message);
g_error_free (error);
goto error_out;
}
if (props.dl_max_datagrams != QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAMS_UNDEFINED &&
!qmi_message_wda_set_data_format_input_set_downlink_data_aggregation_max_datagrams (
input,
props.dl_max_datagrams,
&error)) {
g_printerr ("error: could not set Download data aggregation max datagrams %d: %s\n",
props.dl_max_datagrams, error->message);
g_error_free (error);
goto error_out;
}
if ((props.endpoint_type == QMI_DATA_ENDPOINT_TYPE_UNDEFINED) ^
(props.endpoint_iface_number == QMI_WDA_ENDPOINT_INTERFACE_NUMBER_UNDEFINED)) {
g_printerr ("error: endpoint type and interface number must be both set or both unset\n");
goto error_out;
}
if ((props.endpoint_type != QMI_DATA_ENDPOINT_TYPE_UNDEFINED) &&
(props.endpoint_iface_number != QMI_WDA_ENDPOINT_INTERFACE_NUMBER_UNDEFINED) &&
!qmi_message_wda_set_data_format_input_set_endpoint_info (
input,
props.endpoint_type,
props.endpoint_iface_number,
&error)) {
g_printerr ("error: could not set peripheral endpoint id: %s\n", error->message);
g_error_free (error);
goto error_out;
}
if (props.ul_datagram_max_size != QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAM_SIZE_UNDEFINED &&
!qmi_message_wda_set_data_format_input_set_uplink_data_aggregation_max_size (
input,
props.ul_datagram_max_size,
&error)) {
g_printerr ("error: could not set Upload data aggregation max size %d: %s\n",
props.ul_datagram_max_size, error->message);
g_error_free (error);
goto error_out;
}
if (props.ul_max_datagrams != QMI_WDA_AGGREGATION_PROTOCOL_MAX_DATAGRAMS_UNDEFINED &&
!qmi_message_wda_set_data_format_input_set_uplink_data_aggregation_max_datagrams (
input,
props.ul_max_datagrams,
&error)) {
g_printerr ("error: could not set Upload data aggregation max datagrams %d: %s\n",
props.ul_max_datagrams, error->message);
g_error_free (error);
goto error_out;
}
}
/* Old non key=value format, like this:
* "[(raw-ip|802-3)]"
*/
else {
if (!qmicli_read_wda_link_layer_protocol_from_string (str, &(props.link_layer_protocol))) {
g_printerr ("Unrecognized Link Layer Protocol '%s'\n", str);
goto error_out;
}
}
if (props.link_layer_protocol == QMI_WDA_LINK_LAYER_PROTOCOL_UNKNOWN) {
g_printerr ("error: Link Layer Protocol value is missing\n");
goto error_out;
}
if (!qmi_message_wda_set_data_format_input_set_link_layer_protocol (
input,
props.link_layer_protocol,
&error)) {
g_printerr ("error: couldn't create input data bundle: '%s'\n",
error->message);
g_error_free (error);
goto error_out;
}
return input;
error_out:
qmi_message_wda_set_data_format_input_unref (input);
return NULL;
}
#endif /* HAVE_QMI_MESSAGE_WDA_SET_DATA_FORMAT */
#if defined HAVE_QMI_MESSAGE_WDA_GET_SUPPORTED_MESSAGES
static void
get_supported_messages_ready (QmiClientWda *client,
GAsyncResult *res)
{
QmiMessageWdaGetSupportedMessagesOutput *output;
GError *error = NULL;
GArray *bytearray = NULL;
gchar *str;
output = qmi_client_wda_get_supported_messages_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_wda_get_supported_messages_output_get_result (output, &error)) {
g_printerr ("error: couldn't get supported WDA messages: %s\n", error->message);
g_error_free (error);
qmi_message_wda_get_supported_messages_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully got supported WDA messages:\n",
qmi_device_get_path_display (ctx->device));
qmi_message_wda_get_supported_messages_output_get_list (output, &bytearray, NULL);
str = qmicli_get_supported_messages_list (bytearray ? (const guint8 *)bytearray->data : NULL,
bytearray ? bytearray->len : 0);
g_print ("%s", str);
g_free (str);
qmi_message_wda_get_supported_messages_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_WDA_GET_SUPPORTED_MESSAGES */
void
qmicli_wda_run (QmiDevice *device,
QmiClientWda *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_WDA_SET_DATA_FORMAT
if (set_data_format_str) {
QmiMessageWdaSetDataFormatInput *input;
input = set_data_format_input_create (set_data_format_str);
if (!input) {
operation_shutdown (FALSE);
return;
}
g_debug ("Asynchronously setting data format...");
qmi_client_wda_set_data_format (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)set_data_format_ready,
NULL);
qmi_message_wda_set_data_format_input_unref (input);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT
if (get_data_format_flag) {
g_autoptr(QmiMessageWdaGetDataFormatInput) input = NULL;
if (get_data_format_str) {
input = get_data_format_input_create (get_data_format_str);
if (!input) {
operation_shutdown (FALSE);
return;
}
}
g_debug ("Asynchronously getting data format...");
qmi_client_wda_get_data_format (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_data_format_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_WDA_GET_SUPPORTED_MESSAGES
if (get_supported_messages_flag) {
g_debug ("Asynchronously getting supported WDA messages...");
qmi_client_wda_get_supported_messages (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_supported_messages_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_WDA */

File diff suppressed because it is too large Load Diff

View File

@ -1,566 +0,0 @@
/* -*- 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) 2015-2017 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"
#include "qmicli-helpers.h"
#if defined HAVE_QMI_SERVICE_WMS
#define VALIDATE_UNKNOWN(str) (str ? str : "unknown")
/* Context */
typedef struct {
QmiDevice *device;
QmiClientWms *client;
GCancellable *cancellable;
} Context;
static Context *ctx;
/* Options */
static gboolean get_supported_messages_flag;
static gboolean get_routes_flag;
static gchar *set_routes_str;
static gboolean reset_flag;
static gboolean noop_flag;
static GOptionEntry entries[] = {
#if defined HAVE_QMI_MESSAGE_WMS_GET_SUPPORTED_MESSAGES
{ "wms-get-supported-messages", 0, 0, G_OPTION_ARG_NONE, &get_supported_messages_flag,
"Get supported messages",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_WMS_GET_ROUTES
{ "wms-get-routes", 0, 0, G_OPTION_ARG_NONE, &get_routes_flag,
"Get SMS route information",
NULL
},
#endif
#if defined HAVE_QMI_MESSAGE_WMS_SET_ROUTES
{ "wms-set-routes", 0, 0, G_OPTION_ARG_STRING, &set_routes_str,
"Set SMS route information (keys: type, class, storage, receipt-action)",
"[\"key=value,...\"]"
},
#endif
#if defined HAVE_QMI_MESSAGE_WMS_RESET
{ "wms-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag,
"Reset the service state",
NULL
},
#endif
{ "wms-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a WMS client. Use with `--client-no-release-cid' and/or `--client-cid'",
NULL
},
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
GOptionGroup *
qmicli_wms_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("wms",
"WMS options:",
"Show Wireless Messaging Service options",
NULL,
NULL);
g_option_group_add_entries (group, entries);
return group;
}
gboolean
qmicli_wms_options_enabled (void)
{
static guint n_actions = 0;
static gboolean checked = FALSE;
if (checked)
return !!n_actions;
n_actions = (get_supported_messages_flag +
get_routes_flag +
!!set_routes_str +
reset_flag +
noop_flag);
if (n_actions > 1) {
g_printerr ("error: too many WMS actions requested\n");
exit (EXIT_FAILURE);
}
checked = TRUE;
return !!n_actions;
}
static void
context_free (Context *context)
{
if (!context)
return;
if (context->client)
g_object_unref (context->client);
g_object_unref (context->cancellable);
g_object_unref (context->device);
g_slice_free (Context, context);
}
static void
operation_shutdown (gboolean operation_status)
{
/* Cleanup context and finish async operation */
context_free (ctx);
qmicli_async_operation_done (operation_status, FALSE);
}
#if defined HAVE_QMI_MESSAGE_WMS_GET_SUPPORTED_MESSAGES
static void
get_supported_messages_ready (QmiClientWms *client,
GAsyncResult *res)
{
QmiMessageWmsGetSupportedMessagesOutput *output;
GError *error = NULL;
GArray *bytearray = NULL;
gchar *str;
output = qmi_client_wms_get_supported_messages_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_wms_get_supported_messages_output_get_result (output, &error)) {
g_printerr ("error: couldn't get supported WMS messages: %s\n", error->message);
g_error_free (error);
qmi_message_wms_get_supported_messages_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully got supported WMS messages:\n",
qmi_device_get_path_display (ctx->device));
qmi_message_wms_get_supported_messages_output_get_list (output, &bytearray, NULL);
str = qmicli_get_supported_messages_list (bytearray ? (const guint8 *)bytearray->data : NULL,
bytearray ? bytearray->len : 0);
g_print ("%s", str);
g_free (str);
qmi_message_wms_get_supported_messages_output_unref (output);
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_WMS_GET_SUPPORTED_MESSAGES */
#if defined HAVE_QMI_MESSAGE_WMS_GET_ROUTES
static void
get_routes_ready (QmiClientWms *client,
GAsyncResult *res)
{
g_autoptr(QmiMessageWmsGetRoutesOutput) output = NULL;
GError *error = NULL;
GArray *route_list;
guint i;
output = qmi_client_wms_get_routes_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_wms_get_routes_output_get_result (output, &error)) {
g_printerr ("error: couldn't get SMS routes: %s\n", error->message);
g_error_free (error);
operation_shutdown (FALSE);
return;
}
if (!qmi_message_wms_get_routes_output_get_route_list (output, &route_list, &error)) {
g_printerr ("error: got invalid SMS routes: %s\n", error->message);
g_error_free (error);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Got %u SMS routes:\n", qmi_device_get_path_display (ctx->device),
route_list->len);
for (i = 0; i < route_list->len; i++) {
QmiMessageWmsGetRoutesOutputRouteListElement *route;
route = &g_array_index (route_list, QmiMessageWmsGetRoutesOutputRouteListElement, i);
g_print (" Route #%u:\n", i + 1);
g_print (" Message Type: %s\n", VALIDATE_UNKNOWN (qmi_wms_message_type_get_string (route->message_type)));
g_print (" Message Class: %s\n", VALIDATE_UNKNOWN (qmi_wms_message_class_get_string (route->message_class)));
g_print (" Storage Type: %s\n", VALIDATE_UNKNOWN (qmi_wms_storage_type_get_string (route->storage)));
g_print (" Receipt Action: %s\n", VALIDATE_UNKNOWN (qmi_wms_receipt_action_get_string (route->receipt_action)));
}
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_WMS_GET_ROUTES */
#if defined HAVE_QMI_MESSAGE_WMS_SET_ROUTES
typedef struct {
GArray *route_list;
gboolean message_type_set;
gboolean message_class_set;
gboolean storage_set;
gboolean receipt_action_set;
} SetRoutesContext;
static void
set_routes_context_init (SetRoutesContext *routes_ctx)
{
memset (routes_ctx, 0, sizeof(SetRoutesContext));
routes_ctx->route_list = g_array_new (FALSE, TRUE, sizeof (QmiMessageWmsSetRoutesInputRouteListElement));
}
static void
set_routes_context_destroy (SetRoutesContext *routes_ctx)
{
g_array_unref (routes_ctx->route_list);
}
static gboolean
set_route_properties_handle (const gchar *key,
const gchar *value,
GError **error,
gpointer user_data)
{
SetRoutesContext *routes_ctx = user_data;
QmiMessageWmsSetRoutesInputRouteListElement *cur_route;
gboolean ret = FALSE;
if (!value || !value[0]) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"key '%s' required a value",
key);
return FALSE;
}
if (!routes_ctx->message_type_set && !routes_ctx->message_class_set &&
!routes_ctx->storage_set && !routes_ctx->receipt_action_set) {
QmiMessageWmsSetRoutesInputRouteListElement new_elt;
memset (&new_elt, 0, sizeof (QmiMessageWmsSetRoutesInputRouteListElement));
g_array_append_val (routes_ctx->route_list, new_elt);
}
cur_route = &g_array_index (routes_ctx->route_list,
QmiMessageWmsSetRoutesInputRouteListElement,
routes_ctx->route_list->len - 1);
if (g_ascii_strcasecmp (key, "type") == 0 && !routes_ctx->message_type_set) {
if (!qmicli_read_wms_message_type_from_string (value, &cur_route->message_type)) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"unknown message type '%s'",
value);
return FALSE;
}
routes_ctx->message_type_set = TRUE;
ret = TRUE;
} else if (g_ascii_strcasecmp (key, "class") == 0 && !routes_ctx->message_class_set) {
if (!qmicli_read_wms_message_class_from_string (value, &cur_route->message_class)) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"unknown message class '%s'",
value);
return FALSE;
}
routes_ctx->message_class_set = TRUE;
ret = TRUE;
} else if (g_ascii_strcasecmp (key, "storage") == 0 && !routes_ctx->storage_set) {
if (!qmicli_read_wms_storage_type_from_string (value, &cur_route->storage)) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"unknown storage type '%s'",
value);
return FALSE;
}
routes_ctx->storage_set = TRUE;
ret = TRUE;
} else if (g_ascii_strcasecmp (key, "receipt-action") == 0 && !routes_ctx->receipt_action_set) {
if (!qmicli_read_wms_receipt_action_from_string (value, &cur_route->receipt_action)) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"unknown receipt action '%s'",
value);
return FALSE;
}
routes_ctx->receipt_action_set = TRUE;
ret = TRUE;
}
if (routes_ctx->message_type_set && routes_ctx->message_class_set &&
routes_ctx->storage_set && routes_ctx->receipt_action_set) {
/* We have a complete set of details for this route. Reset the context state. */
routes_ctx->message_type_set = FALSE;
routes_ctx->message_class_set = FALSE;
routes_ctx->storage_set = FALSE;
routes_ctx->receipt_action_set = FALSE;
}
if (!ret) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"unrecognized or duplicate option '%s'",
key);
}
return ret;
}
static QmiMessageWmsSetRoutesInput *
set_routes_input_create (const gchar *str,
GError **error)
{
g_autoptr(QmiMessageWmsSetRoutesInput) input = NULL;
SetRoutesContext routes_ctx;
GError *inner_error = NULL;
set_routes_context_init (&routes_ctx);
if (!qmicli_parse_key_value_string (str,
&inner_error,
set_route_properties_handle,
&routes_ctx)) {
g_propagate_prefixed_error (error,
inner_error,
"couldn't parse input string: ");
set_routes_context_destroy (&routes_ctx);
return NULL;
}
if (routes_ctx.route_list->len == 0) {
g_set_error_literal (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"route list was empty");
set_routes_context_destroy (&routes_ctx);
return NULL;
}
if (routes_ctx.message_type_set || routes_ctx.message_class_set ||
routes_ctx.storage_set || routes_ctx.receipt_action_set) {
g_set_error_literal (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_FAILED,
"final route was missing one or more options");
set_routes_context_destroy (&routes_ctx);
return NULL;
}
/* Create input */
input = qmi_message_wms_set_routes_input_new ();
if (!qmi_message_wms_set_routes_input_set_route_list (input, routes_ctx.route_list, &inner_error)) {
g_propagate_error (error, inner_error);
set_routes_context_destroy (&routes_ctx);
return NULL;
}
set_routes_context_destroy (&routes_ctx);
return g_steal_pointer (&input);
}
static void
set_routes_ready (QmiClientWms *client,
GAsyncResult *res)
{
g_autoptr(QmiMessageWmsSetRoutesOutput) output = NULL;
GError *error = NULL;
output = qmi_client_wms_set_routes_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_wms_set_routes_output_get_result (output, &error)) {
g_printerr ("error: couldn't set SMS routes: %s\n", error->message);
g_error_free (error);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully set SMS routes\n",
qmi_device_get_path_display (ctx->device));
operation_shutdown (TRUE);
}
#endif /* HAVE_QMI_MESSAGE_WMS_SET_ROUTES */
#if defined HAVE_QMI_MESSAGE_WMS_RESET
static void
reset_ready (QmiClientWms *client,
GAsyncResult *res)
{
QmiMessageWmsResetOutput *output;
GError *error = NULL;
output = qmi_client_wms_reset_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_wms_reset_output_get_result (output, &error)) {
g_printerr ("error: couldn't reset the WMS service: %s\n", error->message);
g_error_free (error);
qmi_message_wms_reset_output_unref (output);
operation_shutdown (FALSE);
return;
}
g_print ("[%s] Successfully performed WMS service reset\n",
qmi_device_get_path_display (ctx->device));
qmi_message_wms_reset_output_unref (output);
operation_shutdown (TRUE);
}
#endif
static gboolean
noop_cb (gpointer unused)
{
operation_shutdown (TRUE);
return FALSE;
}
void
qmicli_wms_run (QmiDevice *device,
QmiClientWms *client,
GCancellable *cancellable)
{
/* Initialize context */
ctx = g_slice_new (Context);
ctx->device = g_object_ref (device);
ctx->client = g_object_ref (client);
ctx->cancellable = g_object_ref (cancellable);
#if defined HAVE_QMI_MESSAGE_WMS_GET_SUPPORTED_MESSAGES
if (get_supported_messages_flag) {
g_debug ("Asynchronously getting supported WMS messages...");
qmi_client_wms_get_supported_messages (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_supported_messages_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_WMS_GET_ROUTES
if (get_routes_flag) {
g_debug ("Asynchronously getting SMS routes...");
qmi_client_wms_get_routes (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)get_routes_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_WMS_SET_ROUTES
if (set_routes_str) {
g_autoptr(QmiMessageWmsSetRoutesInput) input = NULL;
GError *error = NULL;
input = set_routes_input_create (set_routes_str, &error);
if (!input) {
g_printerr ("Failed to set route: %s\n", error->message);
g_error_free (error);
operation_shutdown (FALSE);
return;
}
g_debug ("Asynchronously setting SMS routes...");
qmi_client_wms_set_routes (ctx->client,
input,
10,
ctx->cancellable,
(GAsyncReadyCallback)set_routes_ready,
NULL);
return;
}
#endif
#if defined HAVE_QMI_MESSAGE_WMS_RESET
if (reset_flag) {
g_debug ("Asynchronously resetting WMS service...");
qmi_client_wms_reset (ctx->client,
NULL,
10,
ctx->cancellable,
(GAsyncReadyCallback)reset_ready,
NULL);
return;
}
#endif
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
return;
}
g_warn_if_reached ();
}
#endif /* HAVE_QMI_SERVICE_WMS */