2 * uqmi -- tiny QMI support implementation
4 * Copyright (C) 2014-2015 Felix Fietkau <nbd@openwrt.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA.
23 #include "qmi-message.h"
26 #include <libubox/blobmsg.h>
28 /* According to libqmi, a value of -32768 in 5G
29 * indicates that the modem is not connected. */
30 #define _5GNR_NOT_CONNECTED_VALUE -32768
32 static struct qmi_nas_get_tx_rx_info_request tx_rx_req
;
33 static struct qmi_nas_set_system_selection_preference_request sel_req
;
40 print_earfcn_info(uint32_t earfcn
)
42 /* https://www.sqimway.com/lte_band.php */
50 { 0, 599, 1, 2100, "FDD" },
51 { 600, 1199, 2, 1800, "FDD" },
52 { 1200, 1949, 3, 1800, "FDD" },
53 { 1950, 2399, 4, 1700, "FDD" },
54 { 2400, 2649, 5, 850, "FDD" },
55 { 2650, 2749, 6, 800, "FDD" },
56 { 2750, 3449, 7, 2600, "FDD" },
57 { 3450, 3799, 8, 900, "FDD" },
58 { 3800, 4149, 9, 1800, "FDD" },
59 { 4150, 4749, 10, 1700, "FDD" },
60 { 4750, 4999, 11, 1500, "FDD" },
61 { 5000, 5179, 12, 700, "FDD" },
62 { 5180, 5279, 13, 700, "FDD" },
63 { 5280, 5379, 14, 700, "FDD" },
64 { 5730, 5849, 17, 700, "FDD" },
65 { 5850, 5999, 18, 850, "FDD" },
66 { 6000, 6149, 19, 850, "FDD" },
67 { 6150, 6449, 20, 800, "FDD" },
68 { 6450, 6599, 21, 1500, "FDD" },
69 { 6600, 7399, 22, 3500, "FDD" },
70 { 7500, 7699, 23, 2000, "FDD" },
71 { 7700, 8039, 24, 1600, "FDD" },
72 { 8040, 8689, 25, 1900, "FDD" },
73 { 8690, 9039, 26, 850, "FDD" },
74 { 9040, 9209, 27, 800, "FDD" },
75 { 9210, 9659, 28, 700, "FDD" },
76 { 9660, 9769, 29, 700, "SDL" },
77 { 9770, 9869, 30, 2300, "FDD" },
78 { 9870, 9919, 31, 450, "FDD" },
79 { 9920, 10359, 32, 1500, "SDL" },
80 { 36000, 36199, 33, 1900, "TDD" },
81 { 36200, 36349, 34, 2000, "TDD" },
82 { 36350, 36949, 35, 1900, "TDD" },
83 { 36950, 37549, 36, 1900, "TDD" },
84 { 37550, 37749, 37, 1900, "TDD" },
85 { 37750, 38249, 38, 2600, "TDD" },
86 { 38250, 38649, 39, 1900, "TDD" },
87 { 38650, 39649, 40, 2300, "TDD" },
88 { 39650, 41589, 41, 2500, "TDD" },
89 { 41590, 43589, 42, 3500, "TDD" },
90 { 43590, 45589, 43, 3700, "TDD" },
91 { 45590, 46589, 44, 700, "TDD" },
94 for (int i
= 0; i
< (sizeof(earfcn_ranges
) / sizeof(*earfcn_ranges
)); i
++) {
95 if (earfcn
<= earfcn_ranges
[i
].max
&& earfcn
>= earfcn_ranges
[i
].min
) {
96 blobmsg_add_u32(&status
, "band", earfcn_ranges
[i
].band
);
97 blobmsg_add_u32(&status
, "frequency", earfcn_ranges
[i
].freq
);
98 blobmsg_add_string(&status
, "duplex", earfcn_ranges
[i
].duplex
);
104 #define cmd_nas_do_set_system_selection_cb no_cb
105 static enum qmi_cmd_result
106 cmd_nas_do_set_system_selection_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
108 qmi_set_nas_set_system_selection_preference_request(msg
, &sel_req
);
109 return QMI_CMD_REQUEST
;
112 static enum qmi_cmd_result
115 static bool use_sel_req
= false;
119 uqmi_add_command(NULL
, __UQMI_COMMAND_nas_do_set_system_selection
);
125 #define cmd_nas_set_network_modes_cb no_cb
126 static enum qmi_cmd_result
127 cmd_nas_set_network_modes_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
129 static const struct {
131 QmiNasRatModePreference val
;
133 { "cdma", QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X
| QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO
},
134 { "td-scdma", QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA
},
135 { "gsm", QMI_NAS_RAT_MODE_PREFERENCE_GSM
},
136 { "umts", QMI_NAS_RAT_MODE_PREFERENCE_UMTS
},
137 { "lte", QMI_NAS_RAT_MODE_PREFERENCE_LTE
},
138 { "5gnr", QMI_NAS_RAT_MODE_PREFERENCE_5GNR
},
140 QmiNasRatModePreference val
= 0;
144 for (word
= strtok(arg
, ",");
146 word
= strtok(NULL
, ",")) {
149 for (i
= 0; i
< ARRAY_SIZE(modes
); i
++) {
150 if (strcmp(word
, modes
[i
].name
) != 0 &&
151 strcmp(word
, "all") != 0)
159 uqmi_add_error("Invalid network mode");
164 qmi_set(&sel_req
, mode_preference
, val
);
165 return do_sel_network();
168 #define cmd_nas_set_network_preference_cb no_cb
169 static enum qmi_cmd_result
170 cmd_nas_set_network_preference_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
172 QmiNasGsmWcdmaAcquisitionOrderPreference pref
= QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC
;
174 if (!strcmp(arg
, "gsm"))
175 pref
= QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_GSM
;
176 else if (!strcmp(arg
, "wcdma"))
177 pref
= QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_WCDMA
;
179 qmi_set(&sel_req
, gsm_wcdma_acquisition_order_preference
, pref
);
180 return do_sel_network();
183 #define cmd_nas_set_roaming_cb no_cb
184 static enum qmi_cmd_result
185 cmd_nas_set_roaming_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
187 QmiNasRoamingPreference pref
;
189 if (!strcmp(arg
, "any"))
190 pref
= QMI_NAS_ROAMING_PREFERENCE_ANY
;
191 else if (!strcmp(arg
, "only"))
192 pref
= QMI_NAS_ROAMING_PREFERENCE_NOT_OFF
;
193 else if (!strcmp(arg
, "off"))
194 pref
= QMI_NAS_ROAMING_PREFERENCE_OFF
;
196 return uqmi_add_error("Invalid argument");
198 qmi_set(&sel_req
, roaming_preference
, pref
);
199 return do_sel_network();
202 #define cmd_nas_set_mcc_cb no_cb
203 static enum qmi_cmd_result
204 cmd_nas_set_mcc_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
207 int value
= strtoul(arg
, &err
, 10);
209 uqmi_add_error("Invalid MCC value");
213 sel_req
.data
.network_selection_preference
.mcc
= value
;
214 plmn_code_flag
.mcc_is_set
= true;
218 #define cmd_nas_set_mnc_cb no_cb
219 static enum qmi_cmd_result
220 cmd_nas_set_mnc_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
223 int value
= strtoul(arg
, &err
, 10);
225 uqmi_add_error("Invalid MNC value");
229 sel_req
.data
.network_selection_preference
.mnc
= value
;
230 plmn_code_flag
.mnc_is_set
= true;
234 #define cmd_nas_set_plmn_cb no_cb
235 static enum qmi_cmd_result
236 cmd_nas_set_plmn_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
238 sel_req
.set
.network_selection_preference
= 1;
239 sel_req
.data
.network_selection_preference
.mode
= QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC
;
241 if (!plmn_code_flag
.mcc_is_set
&& plmn_code_flag
.mnc_is_set
) {
242 uqmi_add_error("No MCC value");
246 if (plmn_code_flag
.mcc_is_set
&& sel_req
.data
.network_selection_preference
.mcc
) {
247 if (!plmn_code_flag
.mnc_is_set
) {
248 uqmi_add_error("No MNC value");
251 sel_req
.data
.network_selection_preference
.mode
= QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL
;
255 return do_sel_network();
258 #define cmd_nas_initiate_network_register_cb no_cb
259 static enum qmi_cmd_result
260 cmd_nas_initiate_network_register_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
262 static struct qmi_nas_initiate_network_register_request register_req
= {
263 QMI_INIT(action
, QMI_NAS_NETWORK_REGISTER_TYPE_AUTOMATIC
)
266 qmi_set_nas_initiate_network_register_request(msg
, ®ister_req
);
267 return QMI_CMD_REQUEST
;
271 cmd_nas_get_signal_info_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
273 struct qmi_nas_get_signal_info_response res
;
275 bool is_5gnr_connected
= false;
276 bool is_5gnr_endc
= false;
278 qmi_parse_nas_get_signal_info_response(msg
, &res
);
280 /* If 5G NR EN-DC (dual connectivity) is enabled, the mobile device has two connections,
281 * one with the LTE base station, and one with the NR base station.
282 * Therefore an array of signals has to be reported in this case. */
283 is_5gnr_connected
= ((res
.set
._5g_signal_strength
&&
284 ((res
.data
._5g_signal_strength
.rsrp
!= _5GNR_NOT_CONNECTED_VALUE
) ||
285 (res
.data
._5g_signal_strength
.snr
!= _5GNR_NOT_CONNECTED_VALUE
))) ||
286 (res
.set
._5g_signal_strength_extended
&&
287 (res
.data
._5g_signal_strength_extended
!= _5GNR_NOT_CONNECTED_VALUE
)));
288 is_5gnr_endc
= (res
.set
.lte_signal_strength
&& is_5gnr_connected
);
291 a
= blobmsg_open_array(&status
, NULL
);
294 c
= blobmsg_open_table(&status
, NULL
);
295 if (res
.set
.cdma_signal_strength
) {
296 blobmsg_add_string(&status
, "type", "cdma");
297 blobmsg_add_u32(&status
, "rssi", (int32_t) res
.data
.cdma_signal_strength
.rssi
);
298 blobmsg_add_u32(&status
, "ecio", (int32_t) res
.data
.cdma_signal_strength
.ecio
);
301 if (res
.set
.hdr_signal_strength
) {
302 blobmsg_add_string(&status
, "type", "hdr");
303 blobmsg_add_u32(&status
, "rssi", (int32_t) res
.data
.hdr_signal_strength
.rssi
);
304 blobmsg_add_u32(&status
, "ecio", (int32_t) res
.data
.hdr_signal_strength
.ecio
);
305 blobmsg_add_u32(&status
, "io", res
.data
.hdr_signal_strength
.io
);
308 if (res
.set
.gsm_signal_strength
) {
309 blobmsg_add_string(&status
, "type", "gsm");
310 blobmsg_add_u32(&status
, "signal", (int32_t) res
.data
.gsm_signal_strength
);
313 if (res
.set
.wcdma_signal_strength
) {
314 blobmsg_add_string(&status
, "type", "wcdma");
315 blobmsg_add_u32(&status
, "rssi", (int32_t) res
.data
.wcdma_signal_strength
.rssi
);
316 blobmsg_add_u32(&status
, "ecio", (int32_t) res
.data
.wcdma_signal_strength
.ecio
);
319 if (res
.set
.lte_signal_strength
) {
320 blobmsg_add_string(&status
, "type", "lte");
321 blobmsg_add_u32(&status
, "rssi", (int32_t) res
.data
.lte_signal_strength
.rssi
);
322 blobmsg_add_u32(&status
, "rsrq", (int32_t) res
.data
.lte_signal_strength
.rsrq
);
323 blobmsg_add_u32(&status
, "rsrp", (int32_t) res
.data
.lte_signal_strength
.rsrp
);
324 blobmsg_add_double(&status
, "snr", (double) res
.data
.lte_signal_strength
.snr
*0.1);
327 if (res
.set
.tdma_signal_strength
) {
328 blobmsg_add_string(&status
, "type", "tdma");
329 blobmsg_add_u32(&status
, "signal", (int32_t) res
.data
.tdma_signal_strength
);
332 if (is_5gnr_connected
) {
334 blobmsg_close_table(&status
, c
);
335 c
= blobmsg_open_table(&status
, NULL
);
337 blobmsg_add_string(&status
, "type", "5gnr");
338 if (res
.set
._5g_signal_strength
) {
339 if (res
.data
._5g_signal_strength
.rsrp
!= _5GNR_NOT_CONNECTED_VALUE
)
340 blobmsg_add_u32(&status
, "rsrp", (int32_t) res
.data
._5g_signal_strength
.rsrp
);
341 if (res
.data
._5g_signal_strength
.snr
!= _5GNR_NOT_CONNECTED_VALUE
)
342 blobmsg_add_double(&status
, "snr", (double) res
.data
._5g_signal_strength
.snr
*0.1);
345 if (res
.set
._5g_signal_strength_extended
&&
346 (res
.data
._5g_signal_strength_extended
!= _5GNR_NOT_CONNECTED_VALUE
)) {
347 blobmsg_add_u32(&status
, "rsrq", (int32_t) res
.data
._5g_signal_strength_extended
);
351 blobmsg_close_table(&status
, c
);
354 blobmsg_close_array(&status
, a
);
359 print_system_info(uint8_t svc_status
, uint8_t tsvc_status
, bool preferred
, bool system_info
,
360 bool domain_valid
, uint8_t domain
,
361 bool service_cap_valid
, uint8_t service_cap
,
362 bool roaming_status_valid
, uint8_t roaming_status
,
363 bool forbidden_valid
, bool forbidden
,
364 bool network_id_valid
, char *mcc
, char *mnc
,
365 bool lac_valid
, uint16_t lac
)
367 static const char *map_service
[] = {
368 [QMI_NAS_SERVICE_STATUS_NONE
] = "none",
369 [QMI_NAS_SERVICE_STATUS_LIMITED
] = "limited",
370 [QMI_NAS_SERVICE_STATUS_AVAILABLE
] = "available",
371 [QMI_NAS_SERVICE_STATUS_LIMITED_REGIONAL
] = "limited regional",
372 [QMI_NAS_SERVICE_STATUS_POWER_SAVE
] = "power save",
375 static const char *map_roaming
[] = {
376 [QMI_NAS_ROAMING_STATUS_OFF
] = "off",
377 [QMI_NAS_ROAMING_STATUS_ON
] = "on",
378 [QMI_NAS_ROAMING_STATUS_BLINK
] = "blink",
379 [QMI_NAS_ROAMING_STATUS_OUT_OF_NEIGHBORHOOD
] = "out of neighborhood",
380 [QMI_NAS_ROAMING_STATUS_OUT_OF_BUILDING
] = "out of building",
381 [QMI_NAS_ROAMING_STATUS_PREFERRED_SYSTEM
] = "preferred system",
382 [QMI_NAS_ROAMING_STATUS_AVAILABLE_SYSTEM
] = "available system",
383 [QMI_NAS_ROAMING_STATUS_ALLIANCE_PARTNER
] = "alliance partner",
384 [QMI_NAS_ROAMING_STATUS_PREMIUM_PARTNER
] = "premium partner",
385 [QMI_NAS_ROAMING_STATUS_FULL_SERVICE
] = "full service",
386 [QMI_NAS_ROAMING_STATUS_PARTIAL_SERVICE
] = "partial service",
387 [QMI_NAS_ROAMING_STATUS_BANNER_ON
] = "banner on",
388 [QMI_NAS_ROAMING_STATUS_BANNER_OFF
] = "banner off",
391 static const char *map_network
[] = {
392 [QMI_NAS_NETWORK_SERVICE_DOMAIN_NONE
] = "none",
393 [QMI_NAS_NETWORK_SERVICE_DOMAIN_CS
] = "cs",
394 [QMI_NAS_NETWORK_SERVICE_DOMAIN_PS
] = "ps",
395 [QMI_NAS_NETWORK_SERVICE_DOMAIN_CS_PS
] = "cs-ps",
396 [QMI_NAS_NETWORK_SERVICE_DOMAIN_UNKNOWN
] = "unknown",
399 blobmsg_add_string(&status
, "service_status", map_service
[svc_status
]);
400 blobmsg_add_string(&status
, "true_service_status", map_service
[tsvc_status
]);
401 blobmsg_add_u8(&status
, "preferred_data_path", preferred
);
405 blobmsg_add_string(&status
, "domain", map_network
[domain
]);
406 if (service_cap_valid
)
407 blobmsg_add_string(&status
, "service", map_network
[service_cap
]);
408 if (roaming_status_valid
)
409 blobmsg_add_string(&status
, "roaming_status", map_roaming
[roaming_status
]);
411 blobmsg_add_u8(&status
, "forbidden", forbidden
);
412 if (network_id_valid
) {
413 blobmsg_add_string(&status
, "mcc", mcc
);
414 if ((uint8_t)mnc
[2] == 255)
416 blobmsg_add_string(&status
, "mnc", mnc
);
419 blobmsg_add_u32(&status
, "location_area_code", (int32_t) lac
);
424 cmd_nas_get_system_info_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
426 static const char *cell_status
[] = {
427 [QMI_NAS_CELL_ACCESS_STATUS_NORMAL_ONLY
] = "normal",
428 [QMI_NAS_CELL_ACCESS_STATUS_EMERGENCY_ONLY
] = "emergency",
429 [QMI_NAS_CELL_ACCESS_STATUS_NO_CALLS
] = "no calls",
430 [QMI_NAS_CELL_ACCESS_STATUS_ALL_CALLS
] = "all calls",
431 [QMI_NAS_CELL_ACCESS_STATUS_UNKNOWN
] = "unknown",
434 struct qmi_nas_get_system_info_response res
;
437 qmi_parse_nas_get_system_info_response(msg
, &res
);
438 t
= blobmsg_open_table(&status
, NULL
);
439 if (res
.set
.gsm_service_status
) {
440 c
= blobmsg_open_table(&status
, "gsm");
441 print_system_info(res
.data
.gsm_service_status
.service_status
,
442 res
.data
.gsm_service_status
.true_service_status
,
443 res
.data
.gsm_service_status
.preferred_data_path
,
444 res
.set
.gsm_system_info_v2
,
445 res
.data
.gsm_system_info_v2
.domain_valid
,
446 res
.data
.gsm_system_info_v2
.domain
,
447 res
.data
.gsm_system_info_v2
.service_capability_valid
,
448 res
.data
.gsm_system_info_v2
.service_capability
,
449 res
.data
.gsm_system_info_v2
.roaming_status_valid
,
450 res
.data
.gsm_system_info_v2
.roaming_status
,
451 res
.data
.gsm_system_info_v2
.forbidden_valid
,
452 res
.data
.gsm_system_info_v2
.forbidden
,
453 res
.data
.gsm_system_info_v2
.network_id_valid
,
454 res
.data
.gsm_system_info_v2
.mcc
,
455 res
.data
.gsm_system_info_v2
.mnc
,
456 res
.data
.gsm_system_info_v2
.lac_valid
,
457 res
.data
.gsm_system_info_v2
.lac
);
458 if (res
.set
.gsm_system_info_v2
&& res
.data
.gsm_system_info_v2
.cid_valid
)
459 blobmsg_add_u32(&status
, "cell_id",
460 res
.data
.gsm_system_info_v2
.cid
);
461 if (res
.set
.additional_gsm_system_info
&&
462 res
.data
.additional_gsm_system_info
.geo_system_index
!= 0xFFFF)
463 blobmsg_add_u32(&status
, "geo_system_index",
464 res
.data
.additional_gsm_system_info
.geo_system_index
);
465 blobmsg_close_table(&status
, c
);
468 if (res
.set
.wcdma_service_status
) {
469 c
= blobmsg_open_table(&status
, "wcdma");
470 print_system_info(res
.data
.wcdma_service_status
.service_status
,
471 res
.data
.wcdma_service_status
.true_service_status
,
472 res
.data
.wcdma_service_status
.preferred_data_path
,
473 res
.set
.wcdma_system_info_v2
,
474 res
.data
.wcdma_system_info_v2
.domain_valid
,
475 res
.data
.wcdma_system_info_v2
.domain
,
476 res
.data
.wcdma_system_info_v2
.service_capability_valid
,
477 res
.data
.wcdma_system_info_v2
.service_capability
,
478 res
.data
.wcdma_system_info_v2
.roaming_status_valid
,
479 res
.data
.wcdma_system_info_v2
.roaming_status
,
480 res
.data
.wcdma_system_info_v2
.forbidden_valid
,
481 res
.data
.wcdma_system_info_v2
.forbidden
,
482 res
.data
.wcdma_system_info_v2
.network_id_valid
,
483 res
.data
.wcdma_system_info_v2
.mcc
,
484 res
.data
.wcdma_system_info_v2
.mnc
,
485 res
.data
.wcdma_system_info_v2
.lac_valid
,
486 res
.data
.wcdma_system_info_v2
.lac
);
487 if (res
.set
.wcdma_system_info_v2
&& res
.data
.wcdma_system_info_v2
.cid_valid
) {
488 blobmsg_add_u32(&status
, "rnc_id",res
.data
.wcdma_system_info_v2
.cid
/65536);
489 blobmsg_add_u32(&status
, "cell_id",res
.data
.wcdma_system_info_v2
.cid
%65536);
491 if (res
.set
.additional_wcdma_system_info
&&
492 res
.data
.additional_wcdma_system_info
.geo_system_index
!= 0xFFFF)
493 blobmsg_add_u32(&status
, "geo_system_index",
494 res
.data
.additional_wcdma_system_info
.geo_system_index
);
495 blobmsg_close_table(&status
, c
);
498 if (res
.set
.lte_service_status
) {
499 c
= blobmsg_open_table(&status
, "lte");
500 print_system_info(res
.data
.lte_service_status
.service_status
,
501 res
.data
.lte_service_status
.true_service_status
,
502 res
.data
.lte_service_status
.preferred_data_path
,
503 res
.set
.lte_system_info_v2
,
504 res
.data
.lte_system_info_v2
.domain_valid
,
505 res
.data
.lte_system_info_v2
.domain
,
506 res
.data
.lte_system_info_v2
.service_capability_valid
,
507 res
.data
.lte_system_info_v2
.service_capability
,
508 res
.data
.lte_system_info_v2
.roaming_status_valid
,
509 res
.data
.lte_system_info_v2
.roaming_status
,
510 res
.data
.lte_system_info_v2
.forbidden_valid
,
511 res
.data
.lte_system_info_v2
.forbidden
,
512 res
.data
.lte_system_info_v2
.network_id_valid
,
513 res
.data
.lte_system_info_v2
.mcc
,
514 res
.data
.lte_system_info_v2
.mnc
,
515 res
.data
.lte_system_info_v2
.lac_valid
,
516 res
.data
.lte_system_info_v2
.lac
);
517 if (res
.set
.lte_system_info_v2
&& res
.data
.lte_system_info_v2
.tac_valid
)
518 blobmsg_add_u32(&status
, "tracking_area_code",
519 res
.data
.lte_system_info_v2
.tac
);
520 if (res
.set
.lte_system_info_v2
&& res
.data
.lte_system_info_v2
.cid_valid
) {
521 blobmsg_add_u32(&status
, "enodeb_id",res
.data
.lte_system_info_v2
.cid
/256);
522 blobmsg_add_u32(&status
, "cell_id",res
.data
.lte_system_info_v2
.cid
%256);
524 if (res
.set
.additional_lte_system_info
&&
525 res
.data
.additional_lte_system_info
.geo_system_index
!= 0xFFFF)
526 blobmsg_add_u32(&status
, "geo_system_index",
527 res
.data
.additional_lte_system_info
.geo_system_index
);
528 if (res
.set
.lte_voice_support
)
529 blobmsg_add_u8(&status
, "voice_support", res
.data
.lte_voice_support
);
530 if (res
.set
.ims_voice_support
)
531 blobmsg_add_u8(&status
, "ims_voice_support", res
.data
.ims_voice_support
);
532 if (res
.set
.lte_cell_access_status
)
533 blobmsg_add_string(&status
, "cell_access_status",
534 cell_status
[res
.data
.lte_cell_access_status
]);
535 if (res
.set
.network_selection_registration_restriction
)
536 blobmsg_add_u32(&status
, "registration_restriction",
537 res
.data
.network_selection_registration_restriction
);
538 if (res
.set
.lte_registration_domain
)
539 blobmsg_add_u32(&status
, "registration_domain",
540 res
.data
.lte_registration_domain
);
541 if (res
.set
.eutra_with_nr5g_availability
)
542 blobmsg_add_u8(&status
, "5g_nsa_available",
543 res
.data
.eutra_with_nr5g_availability
);
544 if (res
.set
.dcnr_restriction_info
)
545 blobmsg_add_u8(&status
, "dcnr_restriction", res
.data
.dcnr_restriction_info
);
547 blobmsg_close_table(&status
, c
);
550 if (res
.set
.nr5g_service_status_info
) {
551 c
= blobmsg_open_table(&status
, "5gnr");
552 print_system_info(res
.data
.nr5g_service_status_info
.service_status
,
553 res
.data
.nr5g_service_status_info
.true_service_status
,
554 res
.data
.nr5g_service_status_info
.preferred_data_path
,
555 res
.set
.nr5g_system_info
,
556 res
.data
.nr5g_system_info
.domain_valid
,
557 res
.data
.nr5g_system_info
.domain
,
558 res
.data
.nr5g_system_info
.service_capability_valid
,
559 res
.data
.nr5g_system_info
.service_capability
,
560 res
.data
.nr5g_system_info
.roaming_status_valid
,
561 res
.data
.nr5g_system_info
.roaming_status
,
562 res
.data
.nr5g_system_info
.forbidden_valid
,
563 res
.data
.nr5g_system_info
.forbidden
,
564 res
.data
.nr5g_system_info
.network_id_valid
,
565 res
.data
.nr5g_system_info
.mcc
,
566 res
.data
.nr5g_system_info
.mnc
,
567 res
.data
.nr5g_system_info
.lac_valid
,
568 res
.data
.nr5g_system_info
.lac
);
569 if (res
.set
.nr5g_system_info
&& res
.data
.nr5g_system_info
.tac_valid
)
570 blobmsg_add_u32(&status
, "tracking_area_code",
571 res
.data
.nr5g_system_info
.tac
);
572 if (res
.set
.nr5g_system_info
&& res
.data
.nr5g_system_info
.cid_valid
) {
573 blobmsg_add_u32(&status
, "enodeb_id",res
.data
.nr5g_system_info
.cid
/256);
574 blobmsg_add_u32(&status
, "cell_id",res
.data
.nr5g_system_info
.cid
%256);
577 blobmsg_close_table(&status
, c
);
580 blobmsg_close_table(&status
, t
);
583 static enum qmi_cmd_result
584 cmd_nas_get_system_info_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
586 qmi_set_nas_get_system_info_request(msg
);
587 return QMI_CMD_REQUEST
;
591 print_channel_info(int32_t cell_id
, int32_t channel
, uint32_t bw
)
593 static const char *map_bandwidth
[] = {
594 [QMI_NAS_DL_BANDWIDTH_1_4
] = "1.4",
595 [QMI_NAS_DL_BANDWIDTH_3
] = "3",
596 [QMI_NAS_DL_BANDWIDTH_5
] = "5",
597 [QMI_NAS_DL_BANDWIDTH_10
] = "10",
598 [QMI_NAS_DL_BANDWIDTH_15
] = "15",
599 [QMI_NAS_DL_BANDWIDTH_20
] = "20",
600 [QMI_NAS_DL_BANDWIDTH_INVALID
] = "invalid",
601 [QMI_NAS_DL_BANDWIDTH_UNKNOWN
] = "unknown",
604 blobmsg_add_u32(&status
, "cell_id", cell_id
);
605 blobmsg_add_u32(&status
, "channel", channel
);
606 print_earfcn_info(channel
);
607 blobmsg_add_string(&status
, "bandwidth", map_bandwidth
[bw
]);
611 cmd_nas_get_lte_cphy_ca_info_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
613 struct qmi_nas_get_lte_cphy_ca_info_response res
;
614 static const char *scell_state
[] = {
615 [QMI_NAS_SCELL_STATE_DECONFIGURED
] = "deconfigured",
616 [QMI_NAS_SCELL_STATE_DEACTIVATED
] = "deactivated",
617 [QMI_NAS_SCELL_STATE_ACTIVATED
] = "activated",
623 qmi_parse_nas_get_lte_cphy_ca_info_response(msg
, &res
);
624 t
= blobmsg_open_table(&status
, NULL
);
625 if (res
.set
.phy_ca_agg_pcell_info
) {
626 c
= blobmsg_open_table(&status
, "primary");
627 print_channel_info(res
.data
.phy_ca_agg_pcell_info
.physical_cell_id
,
628 res
.data
.phy_ca_agg_pcell_info
.rx_channel
,
629 res
.data
.phy_ca_agg_pcell_info
.dl_bandwidth
);
630 blobmsg_close_table(&status
, c
);
632 if (res
.set
.phy_ca_agg_scell_info
&& res
.data
.phy_ca_agg_secondary_cells_n
) {
633 for (i
= 0; i
< res
.data
.phy_ca_agg_secondary_cells_n
; i
++) {
634 if (res
.data
.phy_ca_agg_secondary_cells
[i
].rx_channel
== 0)
636 sprintf(idx_buf
, "secondary_%d",
637 res
.data
.phy_ca_agg_secondary_cells
[i
].cell_index
);
638 c
= blobmsg_open_table(&status
, idx_buf
);
639 print_channel_info(res
.data
.phy_ca_agg_secondary_cells
[i
].physical_cell_id
,
640 res
.data
.phy_ca_agg_secondary_cells
[i
].rx_channel
,
641 res
.data
.phy_ca_agg_secondary_cells
[i
].dl_bandwidth
);
642 blobmsg_add_string(&status
, "state",
643 scell_state
[res
.data
.phy_ca_agg_secondary_cells
[i
].state
]);
644 blobmsg_close_table(&status
, c
);
647 if (res
.set
.scell_index
)
648 sprintf(idx_buf
, "secondary_%d", res
.data
.scell_index
);
650 sprintf(idx_buf
, "secondary");
651 if (res
.set
.phy_ca_agg_scell_info
&& res
.data
.phy_ca_agg_scell_info
.rx_channel
!= 0) {
652 c
= blobmsg_open_table(&status
, idx_buf
);
653 print_channel_info(res
.data
.phy_ca_agg_scell_info
.physical_cell_id
,
654 res
.data
.phy_ca_agg_scell_info
.rx_channel
,
655 res
.data
.phy_ca_agg_scell_info
.dl_bandwidth
);
656 blobmsg_add_string(&status
, "state",
657 scell_state
[res
.data
.phy_ca_agg_scell_info
.state
]);
658 blobmsg_close_table(&status
, c
);
661 blobmsg_close_table(&status
, t
);
664 static enum qmi_cmd_result
665 cmd_nas_get_lte_cphy_ca_info_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
667 qmi_set_nas_get_lte_cphy_ca_info_request(msg
);
668 return QMI_CMD_REQUEST
;
672 print_chain_info(int8_t radio
, bool tuned
, int32_t rssi
, int32_t ecio
, int32_t rsrp
, int32_t rscp
, uint32_t phase
)
674 blobmsg_add_u8(&status
, "tuned", tuned
);
675 blobmsg_add_double(&status
, "rssi", (double) rssi
*0.1);
676 if (radio
== QMI_NAS_RADIO_INTERFACE_5GNR
) {
677 blobmsg_add_double(&status
, "rsrp", (double) rsrp
*-0.1);
679 else if (radio
== QMI_NAS_RADIO_INTERFACE_LTE
) {
680 blobmsg_add_double(&status
, "rsrq", (double) ecio
*-0.1);
681 blobmsg_add_double(&status
, "rsrp", (double) rsrp
*-0.1);
683 else if (radio
== QMI_NAS_RADIO_INTERFACE_UMTS
) {
684 blobmsg_add_double(&status
, "ecio", (double) ecio
*-0.1);
685 blobmsg_add_double(&status
, "rscp", (double) rscp
*-0.1);
687 if (phase
!= 0xFFFFFFFF)
688 blobmsg_add_double(&status
, "phase", (double) phase
*0.01);
692 cmd_nas_get_tx_rx_info_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
694 struct qmi_nas_get_tx_rx_info_response res
;
697 qmi_parse_nas_get_tx_rx_info_response(msg
, &res
);
698 t
= blobmsg_open_table(&status
, NULL
);
699 if (res
.set
.rx_chain_0_info
) {
700 c
= blobmsg_open_table(&status
, "rx_chain_0");
701 print_chain_info(tx_rx_req
.data
.radio_interface
,
702 res
.data
.rx_chain_0_info
.is_radio_tuned
,
703 res
.data
.rx_chain_0_info
.rx_power
,
704 res
.data
.rx_chain_0_info
.ecio
,
705 res
.data
.rx_chain_0_info
.rsrp
,
706 res
.data
.rx_chain_0_info
.rscp
,
707 res
.data
.rx_chain_0_info
.phase
);
708 blobmsg_close_table(&status
, c
);
710 if (res
.set
.rx_chain_1_info
) {
711 c
= blobmsg_open_table(&status
, "rx_chain_1");
712 print_chain_info(tx_rx_req
.data
.radio_interface
,
713 res
.data
.rx_chain_1_info
.is_radio_tuned
,
714 res
.data
.rx_chain_1_info
.rx_power
,
715 res
.data
.rx_chain_1_info
.ecio
,
716 res
.data
.rx_chain_1_info
.rsrp
,
717 res
.data
.rx_chain_1_info
.rscp
,
718 res
.data
.rx_chain_1_info
.phase
);
719 blobmsg_close_table(&status
, c
);
721 if (res
.set
.rx_chain_2_info
) {
722 c
= blobmsg_open_table(&status
, "rx_chain_2");
723 print_chain_info(tx_rx_req
.data
.radio_interface
,
724 res
.data
.rx_chain_2_info
.is_radio_tuned
,
725 res
.data
.rx_chain_2_info
.rx_power
,
726 res
.data
.rx_chain_2_info
.ecio
,
727 res
.data
.rx_chain_2_info
.rsrp
,
728 res
.data
.rx_chain_2_info
.rscp
,
729 res
.data
.rx_chain_2_info
.phase
);
730 blobmsg_close_table(&status
, c
);
732 if (res
.set
.rx_chain_3_info
) {
733 c
= blobmsg_open_table(&status
, "rx_chain_3");
734 print_chain_info(tx_rx_req
.data
.radio_interface
,
735 res
.data
.rx_chain_3_info
.is_radio_tuned
,
736 res
.data
.rx_chain_3_info
.rx_power
,
737 res
.data
.rx_chain_3_info
.ecio
,
738 res
.data
.rx_chain_3_info
.rsrp
,
739 res
.data
.rx_chain_3_info
.rscp
,
740 res
.data
.rx_chain_3_info
.phase
);
741 blobmsg_close_table(&status
, c
);
743 if (res
.set
.tx_info
) {
744 c
= blobmsg_open_table(&status
, "tx");
745 blobmsg_add_u8(&status
, "traffic", res
.data
.tx_info
.is_in_traffic
);
746 if (res
.data
.tx_info
.is_in_traffic
)
747 blobmsg_add_double(&status
, "tx_power",
748 (double) res
.data
.tx_info
.tx_power
*0.1);
749 blobmsg_close_table(&status
, c
);
751 blobmsg_close_table(&status
, t
);
755 static enum qmi_cmd_result
756 cmd_nas_get_tx_rx_info_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
760 if (!strcmp(arg
, "5gnr"))
761 radio
= QMI_NAS_RADIO_INTERFACE_5GNR
;
762 else if (!strcmp(arg
, "lte"))
763 radio
= QMI_NAS_RADIO_INTERFACE_LTE
;
764 else if (!strcmp(arg
, "umts"))
765 radio
= QMI_NAS_RADIO_INTERFACE_UMTS
;
766 else if (!strcmp(arg
, "gsm"))
767 radio
= QMI_NAS_RADIO_INTERFACE_GSM
;
769 return uqmi_add_error("Invalid argument");
771 qmi_set(&tx_rx_req
, radio_interface
, radio
);
772 qmi_set_nas_get_tx_rx_info_request(msg
, &tx_rx_req
);
773 return QMI_CMD_REQUEST
;
777 print_lte_info(int32_t cell_id
, int16_t rsrp
, int16_t rsrq
, int16_t rssi
)
779 blobmsg_add_u32(&status
, "physical_cell_id", cell_id
);
780 blobmsg_add_double(&status
, "rsrq", ((double)rsrq
)/10);
781 blobmsg_add_double(&status
, "rsrp", ((double)rsrp
)/10);
782 blobmsg_add_double(&status
, "rssi", ((double)rssi
)/10);
786 print_sel_info(int32_t priority
, int32_t high
, int32_t low
)
788 blobmsg_add_u32(&status
, "cell_reselection_priority", priority
);
789 blobmsg_add_u32(&status
, "cell_reselection_low", low
);
790 blobmsg_add_u32(&status
, "cell_reselection_high", high
);
794 cmd_nas_get_cell_location_info_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
796 struct qmi_nas_get_cell_location_info_response res
;
797 void *c
= NULL
, *t
, *cell
, *freq
;
800 qmi_parse_nas_get_cell_location_info_response(msg
, &res
);
801 t
= blobmsg_open_table(&status
, NULL
);
803 if (res
.set
.umts_info_v2
) {
804 c
= blobmsg_open_table(&status
, "umts_info");
805 blobmsg_add_u32(&status
, "location_area_code", res
.data
.umts_info_v2
.lac
);
806 blobmsg_add_u32(&status
, "cell_id", res
.data
.umts_info_v2
.cell_id
);
807 blobmsg_add_u32(&status
, "channel",
808 res
.data
.umts_info_v2
.utra_absolute_rf_channel_number
);
809 blobmsg_add_u32(&status
, "primary_scrambling_code",
810 res
.data
.umts_info_v2
.primary_scrambling_code
);
811 blobmsg_add_u32(&status
, "rscp", res
.data
.umts_info_v2
.rscp
);
812 blobmsg_add_u32(&status
, "ecio", res
.data
.umts_info_v2
.ecio
);
813 for (j
= 0; j
< res
.data
.umts_info_v2
.cell_n
; j
++) {
814 cell
= blobmsg_open_table(&status
, NULL
);
815 blobmsg_add_u32(&status
, "channel",
816 res
.data
.umts_info_v2
.cell
[j
].utra_absolute_rf_channel_number
);
817 blobmsg_add_u32(&status
, "primary_scrambling_code",
818 res
.data
.umts_info_v2
.cell
[j
].primary_scrambling_code
);
819 blobmsg_add_u32(&status
, "rscp", res
.data
.umts_info_v2
.cell
[j
].rscp
);
820 blobmsg_add_u32(&status
, "ecio", res
.data
.umts_info_v2
.cell
[j
].ecio
);
821 blobmsg_close_table(&status
, cell
);
823 for (j
= 0; j
< res
.data
.umts_info_v2
.neighboring_geran_n
; j
++) {
824 cell
= blobmsg_open_table(&status
, "neighboring_geran");
825 blobmsg_add_u32(&status
, "channel",
826 res
.data
.umts_info_v2
.neighboring_geran
[j
].geran_absolute_rf_channel_number
);
827 blobmsg_add_u8(&status
, "network_color_code",
828 res
.data
.umts_info_v2
.neighboring_geran
[j
].network_color_code
);
829 blobmsg_add_u8(&status
, "base_station_color_code",
830 res
.data
.umts_info_v2
.neighboring_geran
[j
].base_station_color_code
);
831 blobmsg_add_u32(&status
, "rssi",
832 res
.data
.umts_info_v2
.neighboring_geran
[j
].rssi
);
833 blobmsg_close_table(&status
, cell
);
835 blobmsg_close_table(&status
, c
);
837 if (res
.set
.intrafrequency_lte_info_v2
) {
838 c
= blobmsg_open_table(&status
, "intrafrequency_lte_info");
839 blobmsg_add_u32(&status
, "tracking_area_code",
840 res
.data
.intrafrequency_lte_info_v2
.tracking_area_code
);
841 blobmsg_add_u32(&status
, "enodeb_id",
842 res
.data
.intrafrequency_lte_info_v2
.global_cell_id
/256);
843 blobmsg_add_u32(&status
, "cell_id",
844 res
.data
.intrafrequency_lte_info_v2
.global_cell_id
%256);
845 blobmsg_add_u32(&status
, "channel",
846 res
.data
.intrafrequency_lte_info_v2
.eutra_absolute_rf_channel_number
);
847 print_earfcn_info(res
.data
.intrafrequency_lte_info_v2
.eutra_absolute_rf_channel_number
);
848 blobmsg_add_u32(&status
, "serving_cell_id",
849 res
.data
.intrafrequency_lte_info_v2
.serving_cell_id
);
850 if (res
.data
.intrafrequency_lte_info_v2
.ue_in_idle
) {
851 blobmsg_add_u32(&status
, "cell_reselection_priority",
852 res
.data
.intrafrequency_lte_info_v2
.cell_reselection_priority
);
853 blobmsg_add_u32(&status
, "s_non_intra_search_threshold",
854 res
.data
.intrafrequency_lte_info_v2
.s_non_intra_search_threshold
);
855 blobmsg_add_u32(&status
, "serving_cell_low_threshold",
856 res
.data
.intrafrequency_lte_info_v2
.serving_cell_low_threshold
);
857 blobmsg_add_u32(&status
, "s_intra_search_threshold",
858 res
.data
.intrafrequency_lte_info_v2
.s_intra_search_threshold
);
860 for (i
= 0; i
< res
.data
.intrafrequency_lte_info_v2
.cell_n
; i
++) {
861 cell
= blobmsg_open_table(&status
, NULL
);
862 print_lte_info(res
.data
.intrafrequency_lte_info_v2
.cell
[i
].physical_cell_id
,
863 res
.data
.intrafrequency_lte_info_v2
.cell
[i
].rsrq
,
864 res
.data
.intrafrequency_lte_info_v2
.cell
[i
].rsrp
,
865 res
.data
.intrafrequency_lte_info_v2
.cell
[i
].rssi
);
866 if (res
.data
.intrafrequency_lte_info_v2
.ue_in_idle
)
867 blobmsg_add_u32(&status
, "cell_selection_rx_level",
868 res
.data
.intrafrequency_lte_info_v2
.cell
[i
].cell_selection_rx_level
);
869 blobmsg_close_table(&status
, cell
);
871 blobmsg_close_table(&status
, c
);
873 if (res
.set
.interfrequency_lte_info
) {
874 if (res
.data
.interfrequency_lte_info
.frequency_n
> 0)
875 c
= blobmsg_open_table(&status
, "interfrequency_lte_info");
876 for (i
= 0; i
< res
.data
.interfrequency_lte_info
.frequency_n
; i
++) {
877 freq
= blobmsg_open_table(&status
, NULL
);
878 blobmsg_add_u32(&status
, "channel",
879 res
.data
.interfrequency_lte_info
.frequency
[i
].eutra_absolute_rf_channel_number
);
880 print_earfcn_info(res
.data
.interfrequency_lte_info
.frequency
[i
].eutra_absolute_rf_channel_number
);
881 if (res
.data
.interfrequency_lte_info
.ue_in_idle
) {
882 print_sel_info(res
.data
.interfrequency_lte_info
.frequency
[i
].cell_reselection_priority
,
883 res
.data
.interfrequency_lte_info
.frequency
[i
].cell_selection_rx_level_high_threshold
,
884 res
.data
.interfrequency_lte_info
.frequency
[i
].cell_selection_rx_level_low_threshold
);
886 for (j
= 0; j
< res
.data
.interfrequency_lte_info
.frequency
[i
].cell_n
; j
++) {
887 cell
= blobmsg_open_table(&status
, NULL
);
888 print_lte_info(res
.data
.interfrequency_lte_info
.frequency
[i
].cell
[j
].physical_cell_id
,
889 res
.data
.interfrequency_lte_info
.frequency
[i
].cell
[j
].rsrq
,
890 res
.data
.interfrequency_lte_info
.frequency
[i
].cell
[j
].rsrp
,
891 res
.data
.interfrequency_lte_info
.frequency
[i
].cell
[j
].rssi
);
892 if (res
.data
.interfrequency_lte_info
.ue_in_idle
)
893 blobmsg_add_u32(&status
, "cell_selection_rx_level",
894 res
.data
.interfrequency_lte_info
.frequency
[i
].cell
[j
].cell_selection_rx_level
);
895 blobmsg_close_table(&status
, cell
);
897 blobmsg_close_table(&status
, freq
);
899 if (res
.data
.interfrequency_lte_info
.frequency_n
> 0)
900 blobmsg_close_table(&status
, c
);
902 if (res
.set
.lte_info_neighboring_gsm
) {
903 if (res
.data
.lte_info_neighboring_gsm
.frequency_n
> 0)
904 c
= blobmsg_open_table(&status
, "lte_info_neighboring_gsm");
905 for (i
= 0; i
< res
.data
.lte_info_neighboring_gsm
.frequency_n
; i
++) {
906 freq
= blobmsg_open_table(&status
, NULL
);
907 blobmsg_add_u32(&status
, "ncc_permitted",
908 res
.data
.lte_info_neighboring_gsm
.frequency
[i
].ncc_permitted
);
909 if (res
.data
.lte_info_neighboring_gsm
.ue_in_idle
) {
910 print_sel_info(res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell_reselection_priority
,
911 res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell_reselection_high_threshold
,
912 res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell_reselection_low_threshold
);
914 for (j
= 0; j
< res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell_n
; j
++) {
915 cell
= blobmsg_open_table(&status
, NULL
);
916 blobmsg_add_u32(&status
, "channel",
917 res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell
[j
].geran_absolute_rf_channel_number
);
918 blobmsg_add_u32(&status
, "base_station_identity_code",
919 res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell
[j
].base_station_identity_code
);
920 blobmsg_add_double(&status
, "rssi",
921 ((double)res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell
[j
].rssi
)/10);
922 if (res
.data
.lte_info_neighboring_gsm
.ue_in_idle
)
923 blobmsg_add_u32(&status
, "cell_selection_rx_level",
924 res
.data
.lte_info_neighboring_gsm
.frequency
[i
].cell
[j
].cell_selection_rx_level
);
925 blobmsg_close_table(&status
, cell
);
927 blobmsg_close_table(&status
, freq
);
929 if (res
.data
.lte_info_neighboring_gsm
.frequency_n
> 0)
930 blobmsg_close_table(&status
, c
);
932 if (res
.set
.lte_info_neighboring_wcdma
) {
933 if (res
.data
.lte_info_neighboring_wcdma
.frequency_n
> 0)
934 c
= blobmsg_open_table(&status
, "lte_info_neighboring_wcdma");
935 for (i
= 0; i
< res
.data
.lte_info_neighboring_wcdma
.frequency_n
; i
++) {
936 freq
= blobmsg_open_table(&status
, NULL
);
937 blobmsg_add_u32(&status
, "channel",
938 res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].utra_absolute_rf_channel_number
);
939 if (res
.data
.lte_info_neighboring_wcdma
.ue_in_idle
) {
940 print_sel_info(res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell_reselection_priority
,
941 res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell_reselection_high_threshold
,
942 res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell_reselection_low_threshold
);
944 for (j
= 0; j
< res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell_n
; j
++) {
945 cell
= blobmsg_open_table(&status
, NULL
);
946 blobmsg_add_u32(&status
, "primary_scrambling_code",
947 res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell
[j
].primary_scrambling_code
);
948 blobmsg_add_double(&status
, "rscp",
949 ((double)res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell
[j
].cpich_rscp
)/10);
950 blobmsg_add_double(&status
, "ecno",
951 ((double)res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell
[j
].cpich_ecno
)/10);
952 if (res
.data
.lte_info_neighboring_wcdma
.ue_in_idle
)
953 blobmsg_add_u32(&status
, "cell_selection_rx_level",
954 res
.data
.lte_info_neighboring_wcdma
.frequency
[i
].cell
[j
].cell_selection_rx_level
);
955 blobmsg_close_table(&status
, cell
);
957 blobmsg_close_table(&status
, freq
);
959 if (res
.data
.lte_info_neighboring_wcdma
.frequency_n
> 0)
960 blobmsg_close_table(&status
, c
);
962 if (res
.set
.umts_info_neighboring_lte
) {
963 if (res
.data
.umts_info_neighboring_lte
.frequency_n
> 0)
964 c
= blobmsg_open_table(&status
, "umts_info_neighboring_lte");
965 for (i
= 0; i
< res
.data
.umts_info_neighboring_lte
.frequency_n
; i
++) {
966 freq
= blobmsg_open_table(&status
, NULL
);
967 blobmsg_add_u32(&status
, "channel",
968 res
.data
.umts_info_neighboring_lte
.frequency
[i
].eutra_absolute_rf_channel_number
);
969 print_earfcn_info(res
.data
.umts_info_neighboring_lte
.frequency
[i
].eutra_absolute_rf_channel_number
);
970 blobmsg_add_u32(&status
, "physical_cell_id",
971 res
.data
.umts_info_neighboring_lte
.frequency
[i
].physical_cell_id
);
972 blobmsg_add_double(&status
, "rsrp",
973 (double) res
.data
.umts_info_neighboring_lte
.frequency
[i
].rsrp
);
974 blobmsg_add_double(&status
, "rsrq",
975 (double) res
.data
.umts_info_neighboring_lte
.frequency
[i
].rsrq
);
976 blobmsg_add_u32(&status
, "cell_selection_rx_level",
977 res
.data
.umts_info_neighboring_lte
.frequency
[i
].cell_selection_rx_level
);
978 blobmsg_close_table(&status
, freq
);
980 if (res
.data
.umts_info_neighboring_lte
.frequency_n
> 0)
981 blobmsg_close_table(&status
, c
);
983 if (res
.set
.nr5g_cell_information
) {
984 c
= blobmsg_open_table(&status
, "nr5g_cell_information");
985 blobmsg_add_u32(&status
, "enodeb_id",
986 res
.data
.nr5g_cell_information
.global_cell_id
/256);
987 blobmsg_add_u32(&status
, "cell_id",
988 res
.data
.nr5g_cell_information
.global_cell_id
%256);
989 blobmsg_add_u32(&status
, "physical_cell_id",
990 res
.data
.nr5g_cell_information
.physical_cell_id
);
991 blobmsg_add_double(&status
, "rsrq", ((double)res
.data
.nr5g_cell_information
.rsrq
)/10);
992 blobmsg_add_double(&status
, "rsrp", ((double)res
.data
.nr5g_cell_information
.rsrp
)/10);
993 blobmsg_add_double(&status
, "snr", ((double)res
.data
.nr5g_cell_information
.snr
)/10);
994 blobmsg_close_table(&status
, c
);
996 if (res
.set
.nr5g_arfcn
) {
997 c
= blobmsg_open_table(&status
, "nr5g_arfcn");
998 blobmsg_add_u32(&status
, "arfcn",
999 res
.data
.nr5g_arfcn
);
1000 blobmsg_close_table(&status
, c
);
1002 blobmsg_close_table(&status
, t
);
1005 static enum qmi_cmd_result
1006 cmd_nas_get_cell_location_info_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
1008 qmi_set_nas_get_cell_location_info_request(msg
);
1009 return QMI_CMD_REQUEST
;
1012 static enum qmi_cmd_result
1013 cmd_nas_get_signal_info_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
1015 qmi_set_nas_get_signal_info_request(msg
);
1016 return QMI_CMD_REQUEST
;
1020 cmd_nas_get_serving_system_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
1022 struct qmi_nas_get_serving_system_response res
;
1023 static const char *reg_states
[] = {
1024 [QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED
] = "not_registered",
1025 [QMI_NAS_REGISTRATION_STATE_REGISTERED
] = "registered",
1026 [QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING
] = "searching",
1027 [QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED
] = "registering_denied",
1028 [QMI_NAS_REGISTRATION_STATE_UNKNOWN
] = "unknown",
1032 qmi_parse_nas_get_serving_system_response(msg
, &res
);
1034 c
= blobmsg_open_table(&status
, NULL
);
1035 if (res
.set
.serving_system
) {
1036 int state
= res
.data
.serving_system
.registration_state
;
1038 if (state
> QMI_NAS_REGISTRATION_STATE_UNKNOWN
)
1039 state
= QMI_NAS_REGISTRATION_STATE_UNKNOWN
;
1041 blobmsg_add_string(&status
, "registration", reg_states
[state
]);
1043 if (res
.set
.current_plmn
) {
1044 blobmsg_add_u32(&status
, "plmn_mcc", res
.data
.current_plmn
.mcc
);
1045 blobmsg_add_u32(&status
, "plmn_mnc", res
.data
.current_plmn
.mnc
);
1046 if (res
.data
.current_plmn
.description
)
1047 blobmsg_add_string(&status
, "plmn_description", res
.data
.current_plmn
.description
);
1050 if (res
.set
.roaming_indicator
)
1051 blobmsg_add_u8(&status
, "roaming", !res
.data
.roaming_indicator
);
1053 blobmsg_close_table(&status
, c
);
1056 static enum qmi_cmd_result
1057 cmd_nas_get_serving_system_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
1059 qmi_set_nas_get_serving_system_request(msg
);
1060 return QMI_CMD_REQUEST
;
1064 cmd_nas_get_plmn_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
1066 struct qmi_nas_get_system_selection_preference_response res
;
1067 static const char *modes
[] = {
1068 [QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC
] = "automatic",
1069 [QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL
] = "manual",
1073 qmi_parse_nas_get_system_selection_preference_response(msg
, &res
);
1075 c
= blobmsg_open_table(&status
, NULL
);
1076 if (res
.set
.network_selection_preference
) {
1077 blobmsg_add_string(&status
, "mode", modes
[res
.data
.network_selection_preference
]);
1079 if (res
.set
.manual_network_selection
) {
1080 blobmsg_add_u32(&status
, "mcc", res
.data
.manual_network_selection
.mcc
);
1081 blobmsg_add_u32(&status
, "mnc", res
.data
.manual_network_selection
.mnc
);
1084 blobmsg_close_table(&status
, c
);
1087 static enum qmi_cmd_result
1088 cmd_nas_get_plmn_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
1090 qmi_set_nas_get_system_selection_preference_request(msg
);
1091 return QMI_CMD_REQUEST
;
1095 cmd_nas_network_scan_cb(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
)
1097 static struct qmi_nas_network_scan_response res
;
1098 const char *network_status
[] = {
1108 const char *radio
[] = {
1109 [QMI_NAS_RADIO_INTERFACE_NONE
] = "none",
1110 [QMI_NAS_RADIO_INTERFACE_CDMA_1X
] = "cdma-1x",
1111 [QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO
] = "cdma-1x_evdo",
1112 [QMI_NAS_RADIO_INTERFACE_AMPS
] = "amps",
1113 [QMI_NAS_RADIO_INTERFACE_GSM
] = "gsm",
1114 [QMI_NAS_RADIO_INTERFACE_UMTS
] = "umts",
1115 [QMI_NAS_RADIO_INTERFACE_LTE
] = "lte",
1116 [QMI_NAS_RADIO_INTERFACE_TD_SCDMA
] = "td-scdma",
1117 [QMI_NAS_RADIO_INTERFACE_5GNR
] = "5gnr",
1119 void *t
, *c
, *info
, *stat
;
1122 qmi_parse_nas_network_scan_response(msg
, &res
);
1124 t
= blobmsg_open_table(&status
, NULL
);
1126 c
= blobmsg_open_array(&status
, "network_info");
1127 for (i
= 0; i
< res
.data
.network_information_n
; i
++) {
1128 info
= blobmsg_open_table(&status
, NULL
);
1129 blobmsg_add_u32(&status
, "mcc", res
.data
.network_information
[i
].mcc
);
1130 blobmsg_add_u32(&status
, "mnc", res
.data
.network_information
[i
].mnc
);
1131 if (res
.data
.network_information
[i
].description
)
1132 blobmsg_add_string(&status
, "description", res
.data
.network_information
[i
].description
);
1133 stat
= blobmsg_open_array(&status
, "status");
1134 for (j
= 0; j
< ARRAY_SIZE(network_status
); j
++) {
1135 if (!(res
.data
.network_information
[i
].network_status
& (1 << j
)))
1138 blobmsg_add_string(&status
, NULL
, network_status
[j
]);
1140 blobmsg_close_array(&status
, stat
);
1141 blobmsg_close_table(&status
, info
);
1143 blobmsg_close_array(&status
, c
);
1145 c
= blobmsg_open_array(&status
, "radio_access_technology");
1146 for (i
= 0; i
< res
.data
.radio_access_technology_n
; i
++) {
1147 const char *r
= "unknown";
1148 int r_i
= res
.data
.radio_access_technology
[i
].radio_interface
;
1150 info
= blobmsg_open_table(&status
, NULL
);
1151 blobmsg_add_u32(&status
, "mcc", res
.data
.radio_access_technology
[i
].mcc
);
1152 blobmsg_add_u32(&status
, "mnc", res
.data
.radio_access_technology
[i
].mnc
);
1153 if (r_i
>= 0 && r_i
< ARRAY_SIZE(radio
))
1156 blobmsg_add_string(&status
, "radio", r
);
1157 blobmsg_close_table(&status
, info
);
1159 blobmsg_close_array(&status
, c
);
1161 blobmsg_close_table(&status
, t
);
1164 static enum qmi_cmd_result
1165 cmd_nas_network_scan_prepare(struct qmi_dev
*qmi
, struct qmi_request
*req
, struct qmi_msg
*msg
, char *arg
)
1167 struct qmi_nas_network_scan_request sreq
= {
1168 QMI_INIT(network_type
,
1169 QMI_NAS_NETWORK_SCAN_TYPE_GSM
|
1170 QMI_NAS_NETWORK_SCAN_TYPE_UMTS
|
1171 QMI_NAS_NETWORK_SCAN_TYPE_LTE
|
1172 QMI_NAS_NETWORK_SCAN_TYPE_TD_SCDMA
),
1175 qmi_set_nas_network_scan_request(msg
, &sreq
);
1176 return QMI_CMD_REQUEST
;