🍉 Sync 2026-06-01 08:47:26

This commit is contained in:
github-actions[bot] 2026-06-01 08:47:26 +08:00
parent 7b700d8d78
commit c92c911d49
7 changed files with 667 additions and 154 deletions

View File

@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=qminfo
PKG_VERSION=0.0.2
PKG_RELEASE:=5
PKG_VERSION=0.0.3
PKG_RELEASE:=6
include $(INCLUDE_DIR)/package.mk

View File

@ -44,6 +44,7 @@ endif
TARGET := qminfo
SRC := qminfo.c
HDRS := qminfo-bands.h qminfo-helpers.h
OBJ := $(SRC:.c=.o)
# pkg-config

337
qminfo/src/qminfo-bands.h Normal file
View File

@ -0,0 +1,337 @@
/*
* qminfo-bands.h
*
* QmiNasActiveBand band number/string mapping tables
* for LTE, NR5G, UMTS and GSM
*
* Part of qminfo simple monitor for QMI modems
* by Konstantine Shevlakov (koshev-msk)
* GPLv3 License. Copyright (c) 2026
*/
#ifndef QMINFO_BANDS_H
#define QMINFO_BANDS_H
#include <libqmi-glib.h>
/* ═══════════════════════════════════════════════════════════════
* LTE: QmiNasActiveBand band number (e.g. 7)
* */
static inline guint active_band_to_lte_band(QmiNasActiveBand band)
{
switch (band) {
case QMI_NAS_ACTIVE_BAND_EUTRAN_1: return 1;
case QMI_NAS_ACTIVE_BAND_EUTRAN_2: return 2;
case QMI_NAS_ACTIVE_BAND_EUTRAN_3: return 3;
case QMI_NAS_ACTIVE_BAND_EUTRAN_4: return 4;
case QMI_NAS_ACTIVE_BAND_EUTRAN_5: return 5;
case QMI_NAS_ACTIVE_BAND_EUTRAN_6: return 6;
case QMI_NAS_ACTIVE_BAND_EUTRAN_7: return 7;
case QMI_NAS_ACTIVE_BAND_EUTRAN_8: return 8;
case QMI_NAS_ACTIVE_BAND_EUTRAN_9: return 9;
case QMI_NAS_ACTIVE_BAND_EUTRAN_10: return 10;
case QMI_NAS_ACTIVE_BAND_EUTRAN_11: return 11;
case QMI_NAS_ACTIVE_BAND_EUTRAN_12: return 12;
case QMI_NAS_ACTIVE_BAND_EUTRAN_13: return 13;
case QMI_NAS_ACTIVE_BAND_EUTRAN_14: return 14;
case QMI_NAS_ACTIVE_BAND_EUTRAN_17: return 17;
case QMI_NAS_ACTIVE_BAND_EUTRAN_18: return 18;
case QMI_NAS_ACTIVE_BAND_EUTRAN_19: return 19;
case QMI_NAS_ACTIVE_BAND_EUTRAN_20: return 20;
case QMI_NAS_ACTIVE_BAND_EUTRAN_21: return 21;
case QMI_NAS_ACTIVE_BAND_EUTRAN_23: return 23;
case QMI_NAS_ACTIVE_BAND_EUTRAN_24: return 24;
case QMI_NAS_ACTIVE_BAND_EUTRAN_25: return 25;
case QMI_NAS_ACTIVE_BAND_EUTRAN_26: return 26;
case QMI_NAS_ACTIVE_BAND_EUTRAN_27: return 27;
case QMI_NAS_ACTIVE_BAND_EUTRAN_28: return 28;
case QMI_NAS_ACTIVE_BAND_EUTRAN_29: return 29;
case QMI_NAS_ACTIVE_BAND_EUTRAN_30: return 30;
case QMI_NAS_ACTIVE_BAND_EUTRAN_31: return 31;
case QMI_NAS_ACTIVE_BAND_EUTRAN_32: return 32;
case QMI_NAS_ACTIVE_BAND_EUTRAN_33: return 33;
case QMI_NAS_ACTIVE_BAND_EUTRAN_34: return 34;
case QMI_NAS_ACTIVE_BAND_EUTRAN_35: return 35;
case QMI_NAS_ACTIVE_BAND_EUTRAN_36: return 36;
case QMI_NAS_ACTIVE_BAND_EUTRAN_37: return 37;
case QMI_NAS_ACTIVE_BAND_EUTRAN_38: return 38;
case QMI_NAS_ACTIVE_BAND_EUTRAN_39: return 39;
case QMI_NAS_ACTIVE_BAND_EUTRAN_40: return 40;
case QMI_NAS_ACTIVE_BAND_EUTRAN_41: return 41;
case QMI_NAS_ACTIVE_BAND_EUTRAN_42: return 42;
case QMI_NAS_ACTIVE_BAND_EUTRAN_43: return 43;
case QMI_NAS_ACTIVE_BAND_EUTRAN_46: return 46;
case QMI_NAS_ACTIVE_BAND_EUTRAN_47: return 47;
case QMI_NAS_ACTIVE_BAND_EUTRAN_48: return 48;
case QMI_NAS_ACTIVE_BAND_EUTRAN_66: return 66;
case QMI_NAS_ACTIVE_BAND_EUTRAN_71: return 71;
case QMI_NAS_ACTIVE_BAND_EUTRAN_125: return 125;
case QMI_NAS_ACTIVE_BAND_EUTRAN_126: return 126;
case QMI_NAS_ACTIVE_BAND_EUTRAN_127: return 127;
case QMI_NAS_ACTIVE_BAND_EUTRAN_250: return 250;
default: return 0;
}
}
/* ═══════════════════════════════════════════════════════════════
* LTE EARFCN band number (based on 3GPP TS 36.101)
* */
static inline guint earfcn_to_lte_band(guint16 earfcn)
{
if (earfcn <= 599) return 1;
if (earfcn <= 1199) return 2;
if (earfcn <= 1949) return 3;
if (earfcn <= 2399) return 4;
if (earfcn <= 2649) return 5;
if (earfcn <= 2749) return 6;
if (earfcn <= 3449) return 7;
if (earfcn <= 3799) return 8;
if (earfcn <= 4149) return 9;
if (earfcn <= 4749) return 10;
if (earfcn <= 4949) return 11;
if (earfcn <= 5179) return 12;
if (earfcn <= 5279) return 13;
if (earfcn <= 5379) return 14;
if (earfcn <= 5499) return 17;
if (earfcn <= 5699) return 17;
if (earfcn <= 5739) return 18;
if (earfcn <= 5849) return 19;
if (earfcn <= 6149) return 20;
if (earfcn <= 6449) return 21;
if (earfcn <= 6599) return 22;
if (earfcn <= 7399) return 23;
if (earfcn <= 7499) return 24;
if (earfcn <= 7699) return 25;
if (earfcn <= 8039) return 26;
if (earfcn <= 8149) return 27;
if (earfcn <= 8299) return 28;
if (earfcn <= 8339) return 29;
if (earfcn <= 8399) return 30;
if (earfcn <= 8449) return 31;
if (earfcn <= 8549) return 32;
if (earfcn >= 36000 && earfcn <= 36199) return 33;
if (earfcn >= 36200 && earfcn <= 36349) return 34;
if (earfcn >= 36350 && earfcn <= 36949) return 35;
if (earfcn >= 36950 && earfcn <= 37549) return 36;
if (earfcn >= 37550 && earfcn <= 37749) return 37;
if (earfcn >= 37750 && earfcn <= 38249) return 38;
if (earfcn >= 38250 && earfcn <= 38649) return 39;
if (earfcn >= 38650 && earfcn <= 39649) return 40;
if (earfcn >= 39650 && earfcn <= 41589) return 41;
if (earfcn >= 41590 && earfcn <= 43589) return 42;
if (earfcn >= 43590 && earfcn <= 45589) return 43;
if (earfcn >= 45590 && earfcn <= 46589) return 44;
if (earfcn >= 46590 && earfcn <= 46789) return 45;
if (earfcn >= 46790 && earfcn <= 54539) return 46;
if (earfcn >= 54540 && earfcn <= 55239) return 47;
if (earfcn >= 55240 && earfcn <= 56739) return 48;
if (earfcn >= 56740 && earfcn <= 58239) return 49;
if (earfcn >= 58240 && earfcn <= 59089) return 50;
if (earfcn >= 59090 && earfcn <= 59139) return 51;
if (earfcn >= 59140 && earfcn <= 60139) return 52;
if (earfcn >= 60140 && earfcn <= 60254) return 53;
if (earfcn >= 60255 && earfcn <= 60304) return 54;
if (earfcn >= 65536 && earfcn <= 66435) return 65;
if (earfcn >= 66436 && earfcn <= 67335) return 66;
if (earfcn >= 67336 && earfcn <= 67535) return 67;
if (earfcn >= 67536 && earfcn <= 67835) return 68;
if (earfcn >= 67836 && earfcn <= 68335) return 69;
if (earfcn >= 68336 && earfcn <= 68585) return 70;
if (earfcn >= 68586 && earfcn <= 68935) return 71;
if (earfcn >= 68936 && earfcn <= 68985) return 72;
if (earfcn >= 68986 && earfcn <= 69035) return 73;
if (earfcn >= 69036 && earfcn <= 69465) return 74;
if (earfcn >= 69466 && earfcn <= 70315) return 75;
if (earfcn >= 70316 && earfcn <= 70365) return 76;
if (earfcn >= 70366 && earfcn <= 70545) return 85;
return 0;
}
/* ═══════════════════════════════════════════════════════════════
* 5G NR: QmiNasActiveBand band number (e.g. 78)
* */
static inline guint active_band_to_nr_band(QmiNasActiveBand band)
{
switch (band) {
case QMI_NAS_ACTIVE_BAND_NR5G_1: return 1;
case QMI_NAS_ACTIVE_BAND_NR5G_2: return 2;
case QMI_NAS_ACTIVE_BAND_NR5G_3: return 3;
case QMI_NAS_ACTIVE_BAND_NR5G_5: return 5;
case QMI_NAS_ACTIVE_BAND_NR5G_7: return 7;
case QMI_NAS_ACTIVE_BAND_NR5G_8: return 8;
case QMI_NAS_ACTIVE_BAND_NR5G_12: return 12;
case QMI_NAS_ACTIVE_BAND_NR5G_13: return 13;
case QMI_NAS_ACTIVE_BAND_NR5G_14: return 14;
case QMI_NAS_ACTIVE_BAND_NR5G_18: return 18;
case QMI_NAS_ACTIVE_BAND_NR5G_20: return 20;
case QMI_NAS_ACTIVE_BAND_NR5G_25: return 25;
case QMI_NAS_ACTIVE_BAND_NR5G_26: return 26;
case QMI_NAS_ACTIVE_BAND_NR5G_28: return 28;
case QMI_NAS_ACTIVE_BAND_NR5G_29: return 29;
case QMI_NAS_ACTIVE_BAND_NR5G_30: return 30;
case QMI_NAS_ACTIVE_BAND_NR5G_34: return 34;
case QMI_NAS_ACTIVE_BAND_NR5G_38: return 38;
case QMI_NAS_ACTIVE_BAND_NR5G_39: return 39;
case QMI_NAS_ACTIVE_BAND_NR5G_40: return 40;
case QMI_NAS_ACTIVE_BAND_NR5G_41: return 41;
case QMI_NAS_ACTIVE_BAND_NR5G_48: return 48;
case QMI_NAS_ACTIVE_BAND_NR5G_50: return 50;
case QMI_NAS_ACTIVE_BAND_NR5G_51: return 51;
case QMI_NAS_ACTIVE_BAND_NR5G_53: return 53;
case QMI_NAS_ACTIVE_BAND_NR5G_65: return 65;
case QMI_NAS_ACTIVE_BAND_NR5G_66: return 66;
case QMI_NAS_ACTIVE_BAND_NR5G_70: return 70;
case QMI_NAS_ACTIVE_BAND_NR5G_71: return 71;
case QMI_NAS_ACTIVE_BAND_NR5G_74: return 74;
case QMI_NAS_ACTIVE_BAND_NR5G_75: return 75;
case QMI_NAS_ACTIVE_BAND_NR5G_76: return 76;
case QMI_NAS_ACTIVE_BAND_NR5G_77: return 77;
case QMI_NAS_ACTIVE_BAND_NR5G_78: return 78;
case QMI_NAS_ACTIVE_BAND_NR5G_79: return 79;
case QMI_NAS_ACTIVE_BAND_NR5G_80: return 80;
case QMI_NAS_ACTIVE_BAND_NR5G_81: return 81;
case QMI_NAS_ACTIVE_BAND_NR5G_82: return 82;
case QMI_NAS_ACTIVE_BAND_NR5G_83: return 83;
case QMI_NAS_ACTIVE_BAND_NR5G_84: return 84;
case QMI_NAS_ACTIVE_BAND_NR5G_85: return 85;
case QMI_NAS_ACTIVE_BAND_NR5G_86: return 86;
case QMI_NAS_ACTIVE_BAND_NR5G_257: return 257;
case QMI_NAS_ACTIVE_BAND_NR5G_258: return 258;
case QMI_NAS_ACTIVE_BAND_NR5G_259: return 259;
case QMI_NAS_ACTIVE_BAND_NR5G_260: return 260;
case QMI_NAS_ACTIVE_BAND_NR5G_261: return 261;
default: return 0;
}
}
/* ═══════════════════════════════════════════════════════════════
* 5G NR (FR1): NR-ARFCN band number (3GPP TS 38.104)
* */
static inline guint nrarfcn_to_nr_band(guint32 nrarfcn)
{
/* FDD bands */
if (nrarfcn >= 422000 && nrarfcn <= 434000) return 1;
if (nrarfcn >= 386000 && nrarfcn <= 398000) return 2;
if (nrarfcn >= 361000 && nrarfcn <= 376000) return 3;
if (nrarfcn >= 173800 && nrarfcn <= 178800) return 5;
if (nrarfcn >= 524000 && nrarfcn <= 538000) return 7;
if (nrarfcn >= 185000 && nrarfcn <= 192000) return 8;
if (nrarfcn >= 145800 && nrarfcn <= 149200) return 12;
if (nrarfcn >= 149200 && nrarfcn <= 151200) return 13;
if (nrarfcn >= 151600 && nrarfcn <= 153600) return 14;
if (nrarfcn >= 172000 && nrarfcn <= 175000) return 18;
if (nrarfcn >= 158200 && nrarfcn <= 164200) return 20;
if (nrarfcn >= 305000 && nrarfcn <= 311800) return 24;
if (nrarfcn >= 386000 && nrarfcn <= 399000) return 25;
if (nrarfcn >= 171800 && nrarfcn <= 178800) return 26;
if (nrarfcn >= 151600 && nrarfcn <= 160600) return 28;
if (nrarfcn >= 143400 && nrarfcn <= 145600) return 29; /* SDL */
if (nrarfcn >= 470000 && nrarfcn <= 472000) return 30;
if (nrarfcn >= 92500 && nrarfcn <= 93500) return 31;
if (nrarfcn >= 422000 && nrarfcn <= 440000) return 65;
if (nrarfcn >= 422000 && nrarfcn <= 440000) return 66; /* same range as 65, need priority */
if (nrarfcn >= 147600 && nrarfcn <= 151600) return 67; /* SDL */
if (nrarfcn >= 150600 && nrarfcn <= 156600) return 68;
if (nrarfcn >= 399000 && nrarfcn <= 404000) return 70;
if (nrarfcn >= 123400 && nrarfcn <= 130400) return 71;
if (nrarfcn >= 92200 && nrarfcn <= 93200) return 72;
if (nrarfcn >= 295000 && nrarfcn <= 303600) return 74;
if (nrarfcn >= 286400 && nrarfcn <= 303400) return 75; /* SDL */
if (nrarfcn >= 285400 && nrarfcn <= 286400) return 76; /* SDL */
if (nrarfcn >= 145600 && nrarfcn <= 149200) return 85;
if (nrarfcn >= 84000 && nrarfcn <= 85000) return 87;
if (nrarfcn >= 84400 && nrarfcn <= 85400) return 88;
if (nrarfcn >= 122400 && nrarfcn <= 130400) return 105;
if (nrarfcn >= 187000 && nrarfcn <= 188000) return 106;
if (nrarfcn >= 286400 && nrarfcn <= 303400) return 109;
/* TDD bands (FR1) */
if (nrarfcn >= 402000 && nrarfcn <= 405000) return 34;
if (nrarfcn >= 514000 && nrarfcn <= 524000) return 38;
if (nrarfcn >= 376000 && nrarfcn <= 384000) return 39;
if (nrarfcn >= 460000 && nrarfcn <= 480000) return 40;
if (nrarfcn >= 499200 && nrarfcn <= 538000) return 41;
if (nrarfcn >= 743334 && nrarfcn <= 795000) return 46;
if (nrarfcn >= 790334 && nrarfcn <= 795000) return 47;
if (nrarfcn >= 636667 && nrarfcn <= 646666) return 48;
if (nrarfcn >= 286400 && nrarfcn <= 303400) return 50;
if (nrarfcn >= 285400 && nrarfcn <= 286400) return 51;
if (nrarfcn >= 496700 && nrarfcn <= 499000) return 53;
if (nrarfcn >= 334000 && nrarfcn <= 335000) return 54;
if (nrarfcn >= 620000 && nrarfcn <= 680000) return 77;
if (nrarfcn >= 620000 && nrarfcn <= 653332) return 78;
if (nrarfcn >= 693334 && nrarfcn <= 733333) return 79;
if (nrarfcn >= 795000 && nrarfcn <= 875000) return 96;
if (nrarfcn >= 828334 && nrarfcn <= 875000) return 104;
/* SUL bands (optional for display) */
if (nrarfcn >= 342000 && nrarfcn <= 357000) return 80;
if (nrarfcn >= 176000 && nrarfcn <= 183000) return 81;
if (nrarfcn >= 166400 && nrarfcn <= 172400) return 82;
if (nrarfcn >= 140600 && nrarfcn <= 149600) return 83;
if (nrarfcn >= 384000 && nrarfcn <= 396000) return 84;
if (nrarfcn >= 342000 && nrarfcn <= 356000) return 86;
if (nrarfcn >= 164800 && nrarfcn <= 169800) return 89;
if (nrarfcn >= 499200 && nrarfcn <= 538000) return 90;
if (nrarfcn >= 285400 && nrarfcn <= 303400) return 91;
if (nrarfcn >= 286400 && nrarfcn <= 303400) return 92;
if (nrarfcn >= 285400 && nrarfcn <= 286400) return 93;
if (nrarfcn >= 286400 && nrarfcn <= 303400) return 94;
if (nrarfcn >= 402000 && nrarfcn <= 405000) return 95;
if (nrarfcn >= 460000 && nrarfcn <= 480000) return 97;
if (nrarfcn >= 376000 && nrarfcn <= 384000) return 98;
if (nrarfcn >= 325300 && nrarfcn <= 332100) return 99;
if (nrarfcn >= 380000 && nrarfcn <= 382000) return 101;
/* FR2 bands (mmWave) если нужны */
if (nrarfcn >= 2054166 && nrarfcn <= 2104165) return 257;
if (nrarfcn >= 2016667 && nrarfcn <= 2070831) return 258;
if (nrarfcn >= 2270833 && nrarfcn <= 2337499) return 259;
if (nrarfcn >= 2229166 && nrarfcn <= 2279165) return 260;
if (nrarfcn >= 2070833 && nrarfcn <= 2084999) return 261;
return 0;
}
/* ═══════════════════════════════════════════════════════════════
* UMTS/WCDMA: QmiNasActiveBand band string (e.g. "B1")
* */
static inline const char *active_band_to_umts_band(QmiNasActiveBand band)
{
switch (band) {
case QMI_NAS_ACTIVE_BAND_WCDMA_2100: return "B1";
case QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900: return "B2";
case QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800: return "B3";
case QMI_NAS_ACTIVE_BAND_WCDMA_1700_US: return "B4";
case QMI_NAS_ACTIVE_BAND_WCDMA_850: return "B5";
case QMI_NAS_ACTIVE_BAND_WCDMA_800: return "B6";
case QMI_NAS_ACTIVE_BAND_WCDMA_2600: return "B7";
case QMI_NAS_ACTIVE_BAND_WCDMA_900: return "B8";
case QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN: return "B9";
case QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN: return "B11";
case QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN: return "B19";
default: return NULL;
}
}
/* ═══════════════════════════════════════════════════════════════
* GSM: QmiNasActiveBand band string (e.g. "DCS1800")
* */
static inline const char *active_band_to_gsm_band(QmiNasActiveBand band)
{
switch (band) {
case QMI_NAS_ACTIVE_BAND_GSM_450: return "GSM450";
case QMI_NAS_ACTIVE_BAND_GSM_480: return "GSM480";
case QMI_NAS_ACTIVE_BAND_GSM_750: return "GSM750";
case QMI_NAS_ACTIVE_BAND_GSM_850: return "GSM850";
case QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED: return "EGSM900";
case QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY: return "GSM900";
case QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS: return "RGSM900";
case QMI_NAS_ACTIVE_BAND_GSM_DCS_1800: return "DCS1800";
case QMI_NAS_ACTIVE_BAND_GSM_PCS_1900: return "PCS1900";
default: return NULL;
}
}
#endif /* QMINFO_BANDS_H */

View File

@ -0,0 +1,92 @@
/*
* qminfo-helpers.h
*
* Pure helper functions for qminfo:
* - unit converters (BW, CSQ, TA)
* - QMI enum to string mappers
* - JSON string escaper
*
* Part of qminfo simple monitor for QMI modems
* by Konstantine Shevlakov (koshev-msk)
* GPLv3 License. Copyright (c) 2026
*/
#ifndef QMINFO_HELPERS_H
#define QMINFO_HELPERS_H
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <libqmi-glib.h>
/* ═══════════════════════════════════════════════════════════════
* Unit converters
* */
/* LTE DL bandwidth index (0-5) → kHz */
static inline guint32 bw_index_to_khz(guint8 bw)
{
static const guint32 t[] = { 1400, 3000, 5000, 10000, 15000, 20000 };
return (bw < 6) ? t[bw] : 0;
}
/* CSQ (0-31) → percent (0-100), -1 if invalid */
static inline int csq_to_percent(int csq)
{
if (csq < 0 || csq > 31) return -1;
return (csq * 100) / 31;
}
/* LTE Timing Advance (μs) → distance in km */
static inline float ta_to_km(guint32 ta)
{
/* d = c * t / 2 = 299792458 * (ta * 10^-6) / 2 / 1000 (km) */
float d = (299792458.0f * (float)ta * 1e-6f) / 2.0f / 1000.0f;
return roundf(d * 100.0f) / 100.0f;
}
/* ═══════════════════════════════════════════════════════════════
* QMI enum string mappers
* */
static inline const char *radio_to_mode(QmiNasRadioInterface iface)
{
switch (iface) {
case QMI_NAS_RADIO_INTERFACE_GSM: return "GSM";
case QMI_NAS_RADIO_INTERFACE_UMTS: return "UMTS";
case QMI_NAS_RADIO_INTERFACE_CDMA_1X: return "CDMA";
case QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO: return "EVDO";
case QMI_NAS_RADIO_INTERFACE_LTE: return "LTE";
case QMI_NAS_RADIO_INTERFACE_5GNR: return "5G NR";
default: return "Unknown";
}
}
static inline const char *reg_state_to_string(QmiNasRegistrationState state)
{
switch (state) {
case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED: return "Not Registered";
case QMI_NAS_REGISTRATION_STATE_REGISTERED: return "Registered";
case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING: return "Searching";
case QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED: return "Denied";
case QMI_NAS_REGISTRATION_STATE_UNKNOWN: return "Unknown";
default: return "Unknown";
}
}
/* ═══════════════════════════════════════════════════════════════
* JSON string escaper
* */
static inline void jstr(char *dst, size_t sz, const char *src)
{
if (!src) { dst[0] = '\0'; return; }
size_t j = 0;
for (size_t i = 0; src[i] && j + 2 < sz; i++) {
if (src[i] == '"' || src[i] == '\\') dst[j++] = '\\';
dst[j++] = src[i];
}
dst[j] = '\0';
}
#endif /* QMINFO_HELPERS_H */

View File

@ -22,6 +22,8 @@
#include <math.h>
#include <unistd.h>
#include <libqmi-glib.h>
#include "qminfo-bands.h"
#include "qminfo-helpers.h"
/* ═══════════════════════════════════════════════════════════════
* main data
@ -55,7 +57,7 @@ typedef struct {
gint lte_ca;
char scc_bands[128];
char scc_bands_json[128];
char scc_bands_json[128];
guint32 bw_ca_total; /* kHz */
gboolean has_rsrp;
@ -115,123 +117,6 @@ typedef enum {
static DeviceMode device_mode = MODE_AUTO;
static gint open_retries = 0; /* retry counter for auto mode */
/* ═══════════════════════════════════════════════════════════════
* helpers
* */
static guint32 bw_index_to_khz(guint8 bw)
{
static const guint32 t[] = { 1400, 3000, 5000, 10000, 15000, 20000 };
return (bw < 6) ? t[bw] : 0;
}
static int csq_to_percent(int csq)
{
if (csq < 0 || csq > 31) return -1;
return (csq * 100) / 31;
}
static float ta_to_km(guint32 ta)
{
/* QMI TA μsec.
* d = c * t / 2 = 299792458 * (ta * 10^-6) / 2 / 1000 (in km) */
float d = (299792458.0f * (float)ta * 1e-6f) / 2.0f / 1000.0f;
return roundf(d * 100.0f) / 100.0f;
}
static const char *radio_to_mode(QmiNasRadioInterface iface)
{
switch (iface) {
case QMI_NAS_RADIO_INTERFACE_GSM: return "GSM";
case QMI_NAS_RADIO_INTERFACE_UMTS: return "UMTS";
case QMI_NAS_RADIO_INTERFACE_CDMA_1X: return "CDMA";
case QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO: return "EVDO";
case QMI_NAS_RADIO_INTERFACE_LTE: return "LTE";
case QMI_NAS_RADIO_INTERFACE_5GNR: return "5G NR";
default: return "Unknown";
}
}
static const char *reg_state_to_string(QmiNasRegistrationState state)
{
switch (state) {
case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED: return "Not Registered";
case QMI_NAS_REGISTRATION_STATE_REGISTERED: return "Registered";
case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING: return "Searching";
case QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED: return "Denied";
case QMI_NAS_REGISTRATION_STATE_UNKNOWN: return "Unknown";
default: return "Unknown";
}
}
static guint active_band_to_lte_band(QmiNasActiveBand band)
{
/* QmiNasActiveBand enum to LTE band */
switch (band) {
case QMI_NAS_ACTIVE_BAND_EUTRAN_1: return 1;
case QMI_NAS_ACTIVE_BAND_EUTRAN_2: return 2;
case QMI_NAS_ACTIVE_BAND_EUTRAN_3: return 3;
case QMI_NAS_ACTIVE_BAND_EUTRAN_4: return 4;
case QMI_NAS_ACTIVE_BAND_EUTRAN_5: return 5;
case QMI_NAS_ACTIVE_BAND_EUTRAN_6: return 6;
case QMI_NAS_ACTIVE_BAND_EUTRAN_7: return 7;
case QMI_NAS_ACTIVE_BAND_EUTRAN_8: return 8;
case QMI_NAS_ACTIVE_BAND_EUTRAN_9: return 9;
case QMI_NAS_ACTIVE_BAND_EUTRAN_10: return 10;
case QMI_NAS_ACTIVE_BAND_EUTRAN_11: return 11;
case QMI_NAS_ACTIVE_BAND_EUTRAN_12: return 12;
case QMI_NAS_ACTIVE_BAND_EUTRAN_13: return 13;
case QMI_NAS_ACTIVE_BAND_EUTRAN_14: return 14;
case QMI_NAS_ACTIVE_BAND_EUTRAN_17: return 17;
case QMI_NAS_ACTIVE_BAND_EUTRAN_18: return 18;
case QMI_NAS_ACTIVE_BAND_EUTRAN_19: return 19;
case QMI_NAS_ACTIVE_BAND_EUTRAN_20: return 20;
case QMI_NAS_ACTIVE_BAND_EUTRAN_21: return 21;
case QMI_NAS_ACTIVE_BAND_EUTRAN_23: return 23;
case QMI_NAS_ACTIVE_BAND_EUTRAN_24: return 24;
case QMI_NAS_ACTIVE_BAND_EUTRAN_25: return 25;
case QMI_NAS_ACTIVE_BAND_EUTRAN_26: return 26;
case QMI_NAS_ACTIVE_BAND_EUTRAN_27: return 27;
case QMI_NAS_ACTIVE_BAND_EUTRAN_28: return 28;
case QMI_NAS_ACTIVE_BAND_EUTRAN_29: return 29;
case QMI_NAS_ACTIVE_BAND_EUTRAN_30: return 30;
case QMI_NAS_ACTIVE_BAND_EUTRAN_31: return 31;
case QMI_NAS_ACTIVE_BAND_EUTRAN_32: return 32;
case QMI_NAS_ACTIVE_BAND_EUTRAN_33: return 33;
case QMI_NAS_ACTIVE_BAND_EUTRAN_34: return 34;
case QMI_NAS_ACTIVE_BAND_EUTRAN_35: return 35;
case QMI_NAS_ACTIVE_BAND_EUTRAN_36: return 36;
case QMI_NAS_ACTIVE_BAND_EUTRAN_37: return 37;
case QMI_NAS_ACTIVE_BAND_EUTRAN_38: return 38;
case QMI_NAS_ACTIVE_BAND_EUTRAN_39: return 39;
case QMI_NAS_ACTIVE_BAND_EUTRAN_40: return 40;
case QMI_NAS_ACTIVE_BAND_EUTRAN_41: return 41;
case QMI_NAS_ACTIVE_BAND_EUTRAN_42: return 42;
case QMI_NAS_ACTIVE_BAND_EUTRAN_43: return 43;
case QMI_NAS_ACTIVE_BAND_EUTRAN_46: return 46;
case QMI_NAS_ACTIVE_BAND_EUTRAN_47: return 47;
case QMI_NAS_ACTIVE_BAND_EUTRAN_48: return 48;
case QMI_NAS_ACTIVE_BAND_EUTRAN_66: return 66;
case QMI_NAS_ACTIVE_BAND_EUTRAN_71: return 71;
case QMI_NAS_ACTIVE_BAND_EUTRAN_125: return 125;
case QMI_NAS_ACTIVE_BAND_EUTRAN_126: return 126;
case QMI_NAS_ACTIVE_BAND_EUTRAN_127: return 127;
case QMI_NAS_ACTIVE_BAND_EUTRAN_250: return 250;
default: return 0;
}
}
static void jstr(char *dst, size_t sz, const char *src)
{
if (!src) { dst[0] = '\0'; return; }
size_t j = 0;
for (size_t i = 0; src[i] && j + 2 < sz; i++) {
if (src[i] == '"' || src[i] == '\\') dst[j++] = '\\';
dst[j++] = src[i];
}
dst[j] = '\0';
}
/* ═══════════════════════════════════════════════════════════════
* Read USB ID from sysfs
* */
@ -295,10 +180,10 @@ static void on_nas_released(QmiDevice *dev, GAsyncResult *res, gpointer ud)
GError *err = NULL;
qmi_device_release_client_finish(device, res, &err);
g_clear_error(&err);
if (nas){
g_object_unref(nas);
nas = NULL;
}
if (nas){
g_object_unref(nas);
nas = NULL;
}
do_close_device();
}
@ -308,10 +193,10 @@ static void on_dms_released(QmiDevice *dev, GAsyncResult *res, gpointer ud)
GError *err = NULL;
qmi_device_release_client_finish(device, res, &err);
g_clear_error(&err);
if (dms){
g_object_unref(dms);
dms = NULL;
}
if (dms){
g_object_unref(dms);
dms = NULL;
}
if (nas) {
qmi_device_release_client(device, QMI_CLIENT(nas),
@ -381,17 +266,30 @@ static void emit_results(void)
printf(" CID : %llu\n",(unsigned long long)info.cid);
printf(" eNB ID : %u\n", info.enb_id);
printf(" Sector : %u\n", info.cell_sector);
if (info.has_arfcn) printf(" RF Chan. : %u\n", info.arfcn);
//if (info.has_arfcn) printf(" RF Chan. : %u\n", info.arfcn);
if (info.has_nr_arfcn && info.nr_arfcn != 0) {
guint nr_band = nrarfcn_to_nr_band(info.nr_arfcn);
if (nr_band)
printf(" RF Chan. : %u (n%d)\n", info.nr_arfcn, nr_band);
else
printf(" RF Chan. : %u\n", info.nr_arfcn);
} else if (info.has_arfcn) {
guint lte_band = earfcn_to_lte_band(info.arfcn);
if (lte_band)
printf(" RF Chan. : %u (B%d)\n", info.arfcn, lte_band);
else
printf(" RF Chan. : %u\n", info.arfcn);
}
if (info.has_pci) printf(" PCI : %u\n", info.pci);
if (dist_km >= 0) printf(" Distance : ~%.2f km (TA=%u)\n", dist_km, info.ta);
if (info.has_bw_dl && strcmp(info.mode, "LTE") == 0)
printf(" BW DL : %.1f MHz\n", bw_index_to_khz(info.bw_dl) / 1000.0f);
if (info.has_bw_dl && strcmp(info.mode, "LTE") == 0)
printf(" BW DL : %.1f MHz\n", bw_index_to_khz(info.bw_dl) / 1000.0f);
printf("-------------------------------------------------\n");
if (info.has_csq) printf(" Strength : %d%% (CSQ %d)\n", csq_pct, info.csq);
if (info.has_csq) printf(" Strength : %d%% (CSQ %d)\n", csq_pct, info.csq);
printf(" RSSI : %d dBm\n", info.rssi);
if (info.has_rsrp) printf(" RSRP : %d dBm\n", (int)roundf(info.rsrp));
if (info.has_rsrq) printf(" RSRQ : %d dB\n", (int)roundf(info.rsrq));
if (info.has_sinr) printf(" %s : %d dB\n", siname, (int)roundf(info.sinr / 10.0f));
if (info.has_sinr) printf(" %s : %d dB\n", siname, (int)roundf(info.sinr / 10.0f));
if (info.is_nr && (info.has_nr_rsrp || info.has_nr_rsrq || info.has_nr_snr)) {
if (info.has_nr_rsrp && info.nr_rsrp > -32700)
printf(" NR RSRP : %d dBm\n", (int)roundf(info.nr_rsrp / 10.0f));
@ -450,7 +348,7 @@ static void emit_results(void)
if (info.nr_nsa && !info.dcnr_restricted)
json_mode_str = "LTE+NR";
else if (info.nr_sa)
json_mode_str = "5GNR";
json_mode_str = "5G NR";
else
json_mode_str = info.mode[0] ? info.mode : "";
@ -477,10 +375,10 @@ static void emit_results(void)
else
printf(" \"chiptemp\" : \"\",\n");
printf(" \"firmware\" : \"%s\",\n", b_fw);
if (info.has_bw_dl && strcmp(info.mode, "LTE") == 0)
printf(" \"bwdl\" : \"%u\",\n", info.has_bw_dl ? (guint32)info.bw_dl : 0);
else
printf(" \"bwdl\" : \"\",\n");
if (info.has_bw_dl && strcmp(info.mode, "LTE") == 0)
printf(" \"bwdl\" : \"%u\",\n", info.has_bw_dl ? (guint32)info.bw_dl : 0);
else
printf(" \"bwdl\" : \"\",\n");
printf(" \"lteca\" : \"%d\",\n", info.has_ca ? info.lte_ca : 0);
printf(" \"enbid\" : \"%u\",\n", info.enb_id);
if (dist_km >= 0.0f)
@ -491,7 +389,7 @@ static void emit_results(void)
printf(" \"scc\" : \"%s\",\n", b_scc);
printf(" \"bwca\" : \"%u\",\n", info.has_ca ? info.bw_ca_total / 1000 : 0);
printf(" \"iccid\" : \"%s\",\n", b_iccid);
printf(" \"imsi\" : \"%s\",\n", b_imsi);
printf(" \"imsi\" : \"%s\",\n", b_imsi);
if (info.has_pci)
printf(" \"pci\" : \"%u\"\n", info.pci);
else
@ -678,13 +576,13 @@ static void on_lte_ca(QmiClientNas *client, GAsyncResult *res, gpointer ud)
info.has_ca = TRUE;
info.lte_ca = 1;
info.scc_bands[0] = '\0';
info.scc_bands_json[0] = '\0';
info.scc_bands_json[0] = '\0';
guint32 total = info.has_bw_dl ? bw_index_to_khz(info.bw_dl) : 0;
char tmp[16];
snprintf(tmp, sizeof(tmp), "B%u", active_band_to_lte_band(scc_band));
g_strlcat(info.scc_bands, tmp, sizeof(info.scc_bands));
snprintf(tmp, sizeof(tmp), "+%u", active_band_to_lte_band(scc_band));
snprintf(tmp, sizeof(tmp), "+%u", active_band_to_lte_band(scc_band));
g_strlcat(info.scc_bands_json, tmp, sizeof(info.scc_bands_json));
total += bw_index_to_khz((guint8)scc_bw);
@ -696,7 +594,7 @@ static void on_lte_ca(QmiClientNas *client, GAsyncResult *res, gpointer ud)
info.has_ca = TRUE;
info.lte_ca = (gint)scc_arr->len;
info.scc_bands[0] = '\0';
info.scc_bands_json[0] = '\0';
info.scc_bands_json[0] = '\0';
guint32 total = info.has_bw_dl ? bw_index_to_khz(info.bw_dl) : 0;
for (guint i = 0; i < scc_arr->len; i++) {
@ -1250,7 +1148,6 @@ static void on_device_open(QmiDevice *dev, GAsyncResult *res, gpointer ud)
GError *err = NULL;
if (!qmi_device_open_finish(device, res, &err)) {
if (device_mode == MODE_AUTO && open_retries == 0) {
/* QMI failed in auto mode — retry with MBIM */
g_clear_error(&err);
open_retries++;
try_open_device();
@ -1262,7 +1159,6 @@ static void on_device_open(QmiDevice *dev, GAsyncResult *res, gpointer ud)
return;
}
/* Restore normal log handler after successful open in auto mode */
if (device_mode == MODE_AUTO)
g_log_set_handler("Qmi",
G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL,
@ -1273,7 +1169,6 @@ static void on_device_open(QmiDevice *dev, GAsyncResult *res, gpointer ud)
(GAsyncReadyCallback)on_dms_client, NULL);
}
/* Open device with flags depending on mode / retry state */
static void try_open_device(void)
{
QmiDeviceOpenFlags flags = QMI_DEVICE_OPEN_FLAGS_PROXY;
@ -1288,7 +1183,6 @@ static void try_open_device(void)
break;
case MODE_AUTO:
default:
/* First attempt: QMI; after retry: MBIM */
mbim = (open_retries > 0);
break;
}
@ -1318,16 +1212,12 @@ static void on_device_new(GObject *src, GAsyncResult *res, gpointer ud)
try_open_device();
}
/* ═══════════════════════════════════════════════════════════════
* Silent log handler suppresses GLib/QMI warnings
* */
static void log_silent(const gchar *domain,
GLogLevelFlags level,
const gchar *message,
gpointer user_data)
{
(void)domain; (void)level; (void)message; (void)user_data;
/* intentionally empty */
}
/* ═══════════════════════════════════════════════════════════════
@ -1365,8 +1255,6 @@ int main(int argc, char *argv[])
info.is_umts = FALSE;
info.is_nr = FALSE;
/* In auto-detect mode, suppress QMI warnings that are expected
* when probing QMI on an MBIM-only device */
if (device_mode == MODE_AUTO) {
g_log_set_handler("Qmi",
G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL,

View File

@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=teleproxy
PKG_VERSION:=4.14.1
PKG_RELEASE:=16
PKG_RELEASE:=17
PKG_MAINTAINER:=Kosntantine Shevlakov <shevlakov@132lan.ru>
PKG_LICENSE:=GPLv2
@ -10,7 +10,7 @@ PKG_LICENSE_FILES:=LICENSE
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/teleproxy/teleproxy.git
PKG_SOURCE_VERSION:=47ecc13c54e2a2ce81002068b9b5cd9e67742a32
PKG_SOURCE_VERSION:=1c989687ef3f163026c102bb5a2eed497e8611ba
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz

View File

@ -0,0 +1,195 @@
From 92322894187a5203277e80b8e462946d8dc3b4a0 Mon Sep 17 00:00:00 2001
From: Nikolay Kulikov <nikolayof23@gmail.com>
Date: Sun, 31 May 2026 18:09:53 +0300
Subject: [PATCH 1/2] common: remove unused code from kprintf.c
The following functions:
reopen_logs()
kdb_write()
nck_pwrite()
are never called, so remove them to eliminate dead code.
The global variable 'reindex_speed' is no longer needed after deleting
the kdb_write() function, so remove it too.
Signed-off-by: Nikolay Kulikov <nikolayof23@gmail.com>
---
src/common/kprintf.c | 68 --------------------------------------------
src/common/kprintf.h | 7 -----
src/engine/engine.h | 1 -
3 files changed, 76 deletions(-)
diff --git a/src/common/kprintf.c b/src/common/kprintf.c
index 64f8213..950b153 100644
--- a/src/common/kprintf.c
+++ b/src/common/kprintf.c
@@ -69,10 +69,6 @@ void reopen_logs_ext (int slave_mode) {
}
}
-void reopen_logs (void) {
- reopen_logs_ext (0);
-}
-
int hexdump (const void *start, const void *end) {
char s[256];
const char *ptr = start;
@@ -101,66 +97,6 @@ int hexdump (const void *start, const void *end) {
return end - start;
}
-
-double reindex_speed = (32 << 20);
-
-void kdb_write (int fd, const void *buf, long long count, const char *filename) {
- assert (count >= 0);
-
- static double total_count;
- static double last_time;
- int write_fail_count = 0;
- while (count) {
- long long l = !reindex_speed ? count : count >= (1 << 20) ? (1 << 20) : count;
-
- if (reindex_speed) {
- double t = get_utime_monotonic ();
- total_count = total_count * exp ((last_time - t) * 0.1);
- last_time = t;
-
- if (total_count > reindex_speed) {
- double k = log (total_count / reindex_speed) * 10;
- assert (k >= 0);
- struct timespec ts;
- ts.tv_nsec = ((int)((k - floor (k)) * 1e9)) % 1000000000;
- ts.tv_sec = (int)k;
- nanosleep (&ts, 0);
- }
- }
- long long w = write (fd, buf, l);
- if (w <= 0) {
- assert (-1 <= w);
- if (write_fail_count < 10000 && (w == 0 || errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
- write_fail_count++;
- continue;
- }
-
- fprintf (stderr, "kdb_write: write %lld bytes to the file '%s' returns %lld. %m\n", l, filename, w);
- exit (1);
- }
- assert (w <= l);
- write_fail_count = 0;
-
- if (reindex_speed) {
- static long long data_after_fsync;
- data_after_fsync += w;
- if (data_after_fsync >= (1 << 20)) {
- if (fsync (fd) < 0) {
- fprintf (stderr, "kdb_write: fsyncing file '%s' failed. %m\n", filename);
- exit (1);
- }
- data_after_fsync = 0;
- }
- double t = get_utime_monotonic ();
- total_count = total_count * exp ((last_time - t) * 0.1);
- last_time = t;
- total_count += w * 0.1;
- }
- count -= w;
- buf += w;
- }
-}
-
static inline void kwrite_print_int (char **s, const char *name, int name_len, int i) {
if (i < 0) {
i = INT_MAX;
@@ -276,7 +212,3 @@ void kprintf (const char *format, ...) {
void nck_write (int fd, const void *data, size_t len) {
if (write (fd, data, len)) {}
}
-
-void nck_pwrite (int fd, const void *data, size_t len, off_t offset) {
- if (pwrite (fd, data, len, offset)) {}
-}
diff --git a/src/common/kprintf.h b/src/common/kprintf.h
index a80b853..00d80bd 100644
--- a/src/common/kprintf.h
+++ b/src/common/kprintf.h
@@ -31,15 +31,9 @@
extern int verbosity;
extern const char *logname;
-void reopen_logs (void);
void reopen_logs_ext (int slave_mode);
int hexdump (const void *start, const void *end);
-extern double reindex_speed;
-
-// safely writes buf to fd, considering write speed limit
-void kdb_write (int fd, const void *buf, long long count, const char *filename);
-
// write message with timestamp and pid, safe to call inside handler
int kwrite (int fd, const void *buf, int count);
@@ -53,4 +47,3 @@ void kprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
} while (0)
void nck_write (int fd, const void *data, size_t len);
-void nck_pwrite (int fd, const void *data, size_t len, off_t offset);
diff --git a/src/engine/engine.h b/src/engine/engine.h
index 337998e..24ee255 100644
--- a/src/engine/engine.h
+++ b/src/engine/engine.h
@@ -202,7 +202,6 @@ ENGINE_INT_PARAM(required_cpu_threads,required_cpu_threads);
ENGINE_INT_PARAM(required_tcp_cpu_threads,required_tcp_cpu_threads);
ENGINE_INT_PARAM(required_tcp_io_threads,required_tcp_io_threads);
-void reopen_logs (void);
int default_main (server_functions_t *F, int argc, char *argv[]);
void default_parse_extra_args (int argc, char *argv[]);
void engine_tl_init (struct tl_act_extra *(*parse)(struct tl_in_state *,long long), void (*stat)(), int (get_op)(struct tl_in_state *), double timeout, const char *name);
From 2373fbd911f4078514111e9ae6f358f443f85608 Mon Sep 17 00:00:00 2001
From: Nikolay Kulikov <nikolayof23@gmail.com>
Date: Sun, 31 May 2026 18:18:52 +0300
Subject: [PATCH 2/2] common: replace nck_write() with a direct call to write()
This function wraps the write() system call, but doesn't perform any
success checks. Replace it with a direct write() call, which will make
the code a bit clearer.
Signed-off-by: Nikolay Kulikov <nikolayof23@gmail.com>
---
src/common/kprintf.c | 6 +-----
src/common/kprintf.h | 2 --
2 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/src/common/kprintf.c b/src/common/kprintf.c
index 950b153..1049e61 100644
--- a/src/common/kprintf.c
+++ b/src/common/kprintf.c
@@ -91,7 +91,7 @@ int hexdump (const void *start, const void *end) {
}
}
s[p ++] = '\n';
- nck_write (2, s, p);
+ write (2, s, p);
ptr += 16;
}
return end - start;
@@ -208,7 +208,3 @@ void kprintf (const char *format, ...) {
//while (flock (2, LOCK_UN) < 0 && errno == EINTR);
errno = old_errno;
}
-
-void nck_write (int fd, const void *data, size_t len) {
- if (write (fd, data, len)) {}
-}
diff --git a/src/common/kprintf.h b/src/common/kprintf.h
index 00d80bd..51578df 100644
--- a/src/common/kprintf.h
+++ b/src/common/kprintf.h
@@ -45,5 +45,3 @@ void kprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
} \
kprintf ((format), ##__VA_ARGS__); \
} while (0)
-
-void nck_write (int fd, const void *data, size_t len);