qmi-nmea: remove non-gps parts of qmicli
This commit is contained in:
parent
1a0e19908a
commit
177bd781d7
@ -192,6 +192,7 @@ SUBSYSTEM=="wwan", ENV{DEVNAME}=="/dev/wwan0qmi0", ENV{DEVTYPE}=="wwan_port", \
|
|||||||
wlr-randr
|
wlr-randr
|
||||||
modemmanager-small
|
modemmanager-small
|
||||||
maps
|
maps
|
||||||
|
qmi-nmea
|
||||||
];
|
];
|
||||||
|
|
||||||
users.users.dan = {
|
users.users.dan = {
|
||||||
|
@ -13,7 +13,7 @@ LDFLAGS=\
|
|||||||
|
|
||||||
default: qmi-nmea
|
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))
|
qmi-nmea: $(patsubst %.c,%.o,$(SRCS))
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
#include "qmicli.h"
|
#include "qmicli.h"
|
||||||
#include "qmicli-helpers.h"
|
#include "qmicli-helpers.h"
|
||||||
|
|
||||||
#define PROGRAM_NAME "qmicli"
|
#define PROGRAM_NAME "qmi-nmea"
|
||||||
#define PROGRAM_VERSION PACKAGE_VERSION
|
#define PROGRAM_VERSION PACKAGE_VERSION
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
@ -85,22 +85,6 @@ static GOptionEntry main_entries[] = {
|
|||||||
"[PATH]"
|
"[PATH]"
|
||||||
#endif
|
#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,
|
{ "device-open-proxy", 'p', 0, G_OPTION_ARG_NONE, &device_open_proxy_flag,
|
||||||
"Request to use the 'qmi-proxy' proxy",
|
"Request to use the 'qmi-proxy' proxy",
|
||||||
NULL
|
NULL
|
||||||
@ -119,10 +103,6 @@ static GOptionEntry main_entries[] = {
|
|||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
#endif
|
#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,
|
{ "client-cid", 0, 0, G_OPTION_ARG_STRING, &client_cid_str,
|
||||||
"Use the given CID, don't allocate a new one",
|
"Use the given CID, don't allocate a new one",
|
||||||
"[CID]"
|
"[CID]"
|
||||||
@ -139,14 +119,6 @@ static GOptionEntry main_entries[] = {
|
|||||||
"Run action with verbose logs, including the debug ones and personal info",
|
"Run action with verbose logs, including the debug ones and personal info",
|
||||||
NULL
|
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 }
|
{ NULL, 0, 0, 0, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -360,69 +332,6 @@ allocate_client_ready (QmiDevice *dev,
|
|||||||
|
|
||||||
/* Run the service-specific action */
|
/* Run the service-specific action */
|
||||||
switch (service) {
|
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:
|
case QMI_SERVICE_LOC:
|
||||||
#if defined HAVE_QMI_SERVICE_LOC
|
#if defined HAVE_QMI_SERVICE_LOC
|
||||||
qmicli_loc_run (dev, QMI_CLIENT_LOC (client), cancellable);
|
qmicli_loc_run (dev, QMI_CLIENT_LOC (client), cancellable);
|
||||||
@ -430,115 +339,6 @@ allocate_client_ready (QmiDevice *dev,
|
|||||||
#else
|
#else
|
||||||
break;
|
break;
|
||||||
#endif
|
#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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -696,10 +496,6 @@ device_open_ready (QmiDevice *dev,
|
|||||||
device_set_instance_id (dev);
|
device_set_instance_id (dev);
|
||||||
else if (get_service_version_info_flag)
|
else if (get_service_version_info_flag)
|
||||||
device_get_service_version_info (dev);
|
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
|
else
|
||||||
device_allocate_client (dev);
|
device_allocate_client (dev);
|
||||||
}
|
}
|
||||||
@ -832,174 +628,12 @@ parse_actions (void)
|
|||||||
{
|
{
|
||||||
guint actions_enabled = 0;
|
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 defined HAVE_QMI_SERVICE_LOC
|
||||||
if (qmicli_loc_options_enabled ()) {
|
if (qmicli_loc_options_enabled ()) {
|
||||||
service = QMI_SERVICE_LOC;
|
service = QMI_SERVICE_LOC;
|
||||||
actions_enabled++;
|
actions_enabled++;
|
||||||
}
|
}
|
||||||
#endif
|
#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? */
|
/* No options? */
|
||||||
if (actions_enabled == 0) {
|
if (actions_enabled == 0) {
|
||||||
g_printerr ("error: no actions specified\n");
|
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 */
|
/* Setup option context, process it and destroy it */
|
||||||
context = g_option_context_new ("- Control QMI devices");
|
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
|
#if defined HAVE_QMI_SERVICE_LOC
|
||||||
g_option_context_add_group (context, qmicli_loc_get_option_group ());
|
g_option_context_add_group (context, qmicli_loc_get_option_group ());
|
||||||
#endif
|
#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);
|
g_option_context_add_main_entries (context, main_entries, NULL);
|
||||||
if (!g_option_context_parse (context, &argc, &argv, &error)) {
|
if (!g_option_context_parse (context, &argc, &argv, &error)) {
|
||||||
g_printerr ("error: %s\n",
|
g_printerr ("error: %s\n",
|
||||||
|
@ -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
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
||||||
|
|
@ -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, ®istration_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, ®istration_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 */
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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
@ -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
@ -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 ();
|
|
||||||
}
|
|
@ -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 */
|
|
@ -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
@ -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,
|
|
||||||
¤t_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,
|
|
||||||
¤t_preferred_voice_so_nam_id,
|
|
||||||
¤t_preferred_voice_so_evrc_capability,
|
|
||||||
¤t_preferred_voice_so_home_page_voice_service_option,
|
|
||||||
¤t_preferred_voice_so_home_origination_voice_service_option,
|
|
||||||
¤t_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,
|
|
||||||
¤t_amr_status_gsm, ¤t_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,
|
|
||||||
¤t_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,
|
|
||||||
¤t_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 */
|
|
@ -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
@ -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 */
|
|
Loading…
Reference in New Issue
Block a user