22
22
#include "link_shell_pdn.h"
23
23
#include "link_settings.h"
24
24
#include "net_utils.h"
25
+ #include "str_utils.h"
25
26
26
27
#define LINK_SHELL_EDRX_VALUE_STR_LENGTH 4
27
28
#define LINK_SHELL_EDRX_PTW_STR_LENGTH 4
@@ -31,6 +32,7 @@ enum link_shell_command {
31
32
LINK_CMD_STATUS = 0 ,
32
33
LINK_CMD_SETTINGS ,
33
34
LINK_CMD_CONEVAL ,
35
+ LINK_CMD_ENVEVAL ,
34
36
LINK_CMD_DEFCONT ,
35
37
LINK_CMD_DEFCONTAUTH ,
36
38
LINK_CMD_RSRP ,
@@ -377,6 +379,28 @@ static const char link_modem_usage_str[] =
377
379
"\n"
378
380
"Several options can be given and they are run in the given order." ;
379
381
382
+ #if defined(CONFIG_LTE_LC_ENV_EVAL_MODULE )
383
+ static const char link_enveval_usage_str [] =
384
+ "Usage: link enveval --eval_type <type> --plmns <plmn1>[,<plmn2>,...] | --cancel\n"
385
+ "Options:\n"
386
+ " --eval_type, [str] Evaluation type:\n"
387
+ " 'dynamic', 'light' or 'full'\n"
388
+ " --plmns, [str] Mobile Country Code and Mobile Network Code pairs\n"
389
+ " --cancel, Cancel ongoing environment evaluation\n"
390
+ " -h, --help, Shows this help information\n"
391
+ "\n"
392
+ "Evaluation types explained:\n"
393
+ " Dynamic: PLMN search is stopped after light search if any of the\n"
394
+ " PLMNs to evaluate were found. Search is continued over all\n"
395
+ " frequency bands if light search did not find any results.\n"
396
+ "\n"
397
+ " Light: PLMN search is stopped after light search even if no PLMNs\n"
398
+ " to evaluate were found.\n"
399
+ "\n"
400
+ " Full: PLMN search covers all channels in all supported frequency\n"
401
+ " bands.\n" ;
402
+ #endif /* CONFIG_LTE_LC_ENV_EVAL_MODULE */
403
+
380
404
/* The following do not have short options */
381
405
enum {
382
406
LINK_SHELL_OPT_MEM_SLOT_1 = 1001 ,
@@ -424,6 +448,8 @@ enum {
424
448
LINK_SHELL_OPT_MODEM_INIT ,
425
449
LINK_SHELL_OPT_MODEM_SHUTDOWN ,
426
450
LINK_SHELL_OPT_MODEM_SHUTDOWN_CFUN0 ,
451
+ LINK_SHELL_OPT_ENVEVAL_EVAL_TYPE ,
452
+ LINK_SHELL_OPT_ENVEVAL_PLMNS ,
427
453
};
428
454
429
455
/* Specifying the expected options (both long and short) */
@@ -502,6 +528,8 @@ static struct option long_options[] = {
502
528
{ "init" , no_argument , 0 , LINK_SHELL_OPT_MODEM_INIT },
503
529
{ "shutdown" , no_argument , 0 , LINK_SHELL_OPT_MODEM_SHUTDOWN },
504
530
{ "shutdown_cfun0" , no_argument , 0 , LINK_SHELL_OPT_MODEM_SHUTDOWN_CFUN0 },
531
+ { "eval_type" , required_argument , 0 , LINK_SHELL_OPT_ENVEVAL_EVAL_TYPE },
532
+ { "plmns" , required_argument , 0 , LINK_SHELL_OPT_ENVEVAL_PLMNS },
505
533
{ 0 , 0 , 0 , 0 }
506
534
};
507
535
@@ -521,6 +549,11 @@ static void link_shell_print_usage(enum link_shell_command command)
521
549
case LINK_CMD_DEFCONTAUTH :
522
550
mosh_print_no_format (link_defcontauth_usage_str );
523
551
break ;
552
+ #if defined(CONFIG_LTE_LC_ENV_EVAL_MODULE )
553
+ case LINK_CMD_ENVEVAL :
554
+ mosh_print_no_format (link_enveval_usage_str );
555
+ break ;
556
+ #endif /* CONFIG_LTE_LC_ENV_EVAL_MODULE */
524
557
case LINK_CMD_CONNECT :
525
558
mosh_print_no_format (link_connect_usage_str );
526
559
break ;
@@ -649,6 +682,25 @@ static enum lte_lc_neighbor_search_type
649
682
return search_type ;
650
683
}
651
684
685
+ #if defined(CONFIG_LTE_LC_ENV_EVAL_MODULE )
686
+ #define MOSH_ENVEVAL_EVAL_TYPE_NONE 0xFF
687
+
688
+ static enum lte_lc_env_eval_type link_shell_string_to_env_eval_type (const char * eval_type_str )
689
+ {
690
+ enum lte_lc_env_eval_type eval_type = MOSH_ENVEVAL_EVAL_TYPE_NONE ;
691
+
692
+ if (strcmp (eval_type_str , "dynamic" ) == 0 ) {
693
+ eval_type = LTE_LC_ENV_EVAL_TYPE_DYNAMIC ;
694
+ } else if (strcmp (eval_type_str , "light" ) == 0 ) {
695
+ eval_type = LTE_LC_ENV_EVAL_TYPE_LIGHT ;
696
+ } else if (strcmp (eval_type_str , "full" ) == 0 ) {
697
+ eval_type = LTE_LC_ENV_EVAL_TYPE_FULL ;
698
+ }
699
+
700
+ return eval_type ;
701
+ }
702
+ #endif /* CONFIG_LTE_LC_ENV_EVAL_MODULE */
703
+
652
704
int link_shell_get_and_print_current_system_modes (
653
705
enum lte_lc_system_mode * sys_mode_current ,
654
706
enum lte_lc_system_mode_preference * sys_mode_preferred ,
@@ -827,6 +879,170 @@ static int link_shell_coneval(const struct shell *shell, size_t argc, char **arg
827
879
return 0 ;
828
880
}
829
881
882
+ #if defined(CONFIG_LTE_LC_ENV_EVAL_MODULE )
883
+ static int link_shell_string_to_env_eval_plmn_list (
884
+ char * plmn_str ,
885
+ struct lte_lc_env_eval_plmn * plmn_list ,
886
+ uint8_t * plmn_count )
887
+ {
888
+ int ret = 0 ;
889
+ size_t plmn_str_len ;
890
+ char * plmn_ptr ;
891
+ uint8_t count = 0 ;
892
+
893
+ __ASSERT_NO_MSG (plmn_str != NULL );
894
+ __ASSERT_NO_MSG (plmn_list != NULL );
895
+ __ASSERT_NO_MSG (plmn_count != NULL );
896
+
897
+ * plmn_count = 0 ;
898
+
899
+ plmn_str_len = strlen (plmn_str );
900
+ plmn_ptr = plmn_str ;
901
+
902
+ /* Replace commas with nul-terminators. */
903
+ for (int i = 0 ; i < plmn_str_len ; i ++ ) {
904
+ if (plmn_ptr [i ] == ',' ) {
905
+ plmn_ptr [i ] = '\0' ;
906
+ }
907
+ }
908
+
909
+ while (plmn_ptr < (plmn_str + plmn_str_len )) {
910
+ if (count >= CONFIG_LTE_LC_ENV_EVAL_MAX_PLMN_COUNT ) {
911
+ mosh_error ("Number of PLMNs exceeds CONFIG_LTE_LC_ENV_EVAL_MAX_PLMN_COUNT"
912
+ " (%d)" ,
913
+ CONFIG_LTE_LC_ENV_EVAL_MAX_PLMN_COUNT );
914
+ return - EINVAL ;
915
+ }
916
+
917
+ if (strlen (plmn_ptr ) < 5 ) {
918
+ mosh_error ("Invalid PLMN: %s" , plmn_ptr );
919
+ return - EBADMSG ;
920
+ }
921
+
922
+ /* Read MNC and store as integer. The MNC starts as the fourth character
923
+ * in the string, following three characters long MCC.
924
+ */
925
+ ret = mosh_string_to_int (& plmn_ptr [3 ], 10 , & plmn_list [count ].mnc );
926
+ if (ret ) {
927
+ return - EBADMSG ;
928
+ }
929
+
930
+ /* Nul-terminate MCC, read and store it. */
931
+ plmn_ptr [3 ] = '\0' ;
932
+ ret = mosh_string_to_int (& plmn_ptr [0 ], 10 , & plmn_list [count ].mcc );
933
+ if (ret ) {
934
+ return - EBADMSG ;
935
+ }
936
+
937
+ if (plmn_list [count ].mcc == 0 || plmn_list [count ].mnc == 0 ) {
938
+ mosh_error ("Invalid PLMN: MCC: %03d, MNC: %02d" ,
939
+ plmn_list [count ].mcc , plmn_list [count ].mnc );
940
+ return - EBADMSG ;
941
+ }
942
+
943
+ count ++ ;
944
+
945
+ /* Skip parsed PLMN, which is at least 5 digits. */
946
+ plmn_ptr += 5 ;
947
+
948
+ if (* plmn_ptr != '\0' ) {
949
+ /* Skip 6th digit.*/
950
+ plmn_ptr ++ ;
951
+ }
952
+ /* Skip nul-terminator. */
953
+ plmn_ptr ++ ;
954
+ }
955
+
956
+ * plmn_count = count ;
957
+
958
+ return ret ;
959
+ }
960
+
961
+ static int link_shell_enveval (const struct shell * shell , size_t argc , char * * argv )
962
+ {
963
+ int ret ;
964
+ struct lte_lc_env_eval_plmn plmn_list [CONFIG_LTE_LC_ENV_EVAL_MAX_PLMN_COUNT ] = {0 };
965
+ struct lte_lc_env_eval_params params = {
966
+ .eval_type = MOSH_ENVEVAL_EVAL_TYPE_NONE ,
967
+ .plmn_list = plmn_list
968
+ };
969
+ bool cancel = false;
970
+
971
+ if (argc < 2 ) {
972
+ goto show_usage ;
973
+ }
974
+
975
+ optreset = 1 ;
976
+ optind = 1 ;
977
+ int opt ;
978
+
979
+ while ((opt = getopt_long (argc , argv , short_options , long_options , NULL )) != -1 ) {
980
+ switch (opt ) {
981
+ case LINK_SHELL_OPT_ENVEVAL_EVAL_TYPE :
982
+ params .eval_type = link_shell_string_to_env_eval_type (optarg );
983
+ if (params .eval_type == MOSH_ENVEVAL_EVAL_TYPE_NONE ) {
984
+ mosh_error ("Unknown evaluation type. See usage:" );
985
+ goto show_usage ;
986
+ }
987
+ break ;
988
+ case LINK_SHELL_OPT_ENVEVAL_PLMNS :
989
+ ret = link_shell_string_to_env_eval_plmn_list (
990
+ optarg , params .plmn_list , & params .plmn_count );
991
+ if (ret ) {
992
+ mosh_error ("Invalid PLMN list. See usage:" );
993
+ goto show_usage ;
994
+ }
995
+ break ;
996
+ case LINK_SHELL_OPT_STOP :
997
+ cancel = true;
998
+ break ;
999
+
1000
+ case 'h' :
1001
+ goto show_usage ;
1002
+ case '?' :
1003
+ default :
1004
+ mosh_error ("Unknown option (%s). See usage:" , argv [optind - 1 ]);
1005
+ goto show_usage ;
1006
+ }
1007
+ }
1008
+
1009
+ if (cancel ) {
1010
+ mosh_print ("Cancelling environment evaluation..." );
1011
+ ret = lte_lc_env_eval_cancel ();
1012
+ if (ret ) {
1013
+ mosh_error ("lte_lc_env_eval_cancel() returned %d" , ret );
1014
+ return - ENOEXEC ;
1015
+ }
1016
+ return 0 ;
1017
+ }
1018
+
1019
+ /* Validate that both eval_type and plmns were provided */
1020
+ if (params .eval_type == MOSH_ENVEVAL_EVAL_TYPE_NONE ) {
1021
+ mosh_error ("Evaluation type must be specified. See usage:" );
1022
+ goto show_usage ;
1023
+ }
1024
+
1025
+ if (params .plmn_count == 0 ) {
1026
+ mosh_error ("At least one PLMN must be specified. See usage:" );
1027
+ goto show_usage ;
1028
+ }
1029
+
1030
+ mosh_print ("Starting environment evaluation for %zu PLMN(s)..." , params .plmn_count );
1031
+
1032
+ ret = lte_lc_env_eval (& params );
1033
+ if (ret ) {
1034
+ mosh_error ("lte_lc_env_eval() returned %d" , ret );
1035
+ return - ENOEXEC ;
1036
+ }
1037
+
1038
+ return 0 ;
1039
+
1040
+ show_usage :
1041
+ link_shell_print_usage (LINK_CMD_ENVEVAL );
1042
+ return - EINVAL ;
1043
+ }
1044
+ #endif /* CONFIG_LTE_LC_ENV_EVAL_MODULE */
1045
+
830
1046
static int link_shell_defcont (const struct shell * shell , size_t argc , char * * argv )
831
1047
{
832
1048
int ret = 0 ;
@@ -2756,6 +2972,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
2756
2972
edrx , NULL ,
2757
2973
"Enable/disable eDRX with default or with custom parameters." ,
2758
2974
link_shell_edrx , 0 , 10 ),
2975
+ #if defined(CONFIG_LTE_LC_ENV_EVAL_MODULE )
2976
+ SHELL_CMD_ARG (
2977
+ enveval , NULL ,
2978
+ "Perform environment evaluation for specified PLMNs." ,
2979
+ link_shell_enveval , 0 , 20 ),
2980
+ #endif /* CONFIG_LTE_LC_ENV_EVAL_MODULE */
2759
2981
SHELL_CMD_ARG (
2760
2982
funmode , NULL ,
2761
2983
"Set/read functional modes of the modem." ,
0 commit comments