Work on VTY interface:
authorAndreas.Eversberg <jolly@eversberg.eu>
Thu, 13 May 2010 12:51:22 +0000 (12:51 +0000)
committerAndreas.Eversberg <jolly@eversberg.eu>
Thu, 13 May 2010 12:51:22 +0000 (12:51 +0000)
- Load and save of config now works.
- Network search is displayed on VTY and the result can be selected there.
- Manual/auto mode can be selected via VTY and saved.

src/host/layer23/include/osmocom/file.h
src/host/layer23/include/osmocom/support.h
src/host/layer23/include/osmocom/telnet_interface.h
src/host/layer23/src/app_mobile.c
src/host/layer23/src/gsm322.c
src/host/layer23/src/main.c
src/host/layer23/src/support.c
src/host/layer23/src/telnet_interface.c
src/host/layer23/src/vty/command.c
src/host/layer23/src/vty_interface.c

index 289347d..249064d 100644 (file)
@@ -2,7 +2,10 @@
 #define _OSMOCOM_FILE_H
 
 #include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #define OSMOCOM_CONFDIR "/etc/osmocom/"
@@ -30,5 +33,48 @@ static inline OSMOCOM_FILE *osmocom_fopen(const char *name, const char *mode)
 #define osmocom_fwrite fwrite
 #define osmocom_feof feof
 #define osmocom_fclose fclose
+static inline int OSMOCOM_UNLINK(const char *name)
+{
+       char filename[strlen(OSMOCOM_CONFDIR) + strlen(name) + 1];
+
+       strcpy(filename, OSMOCOM_CONFDIR);
+       strcat(filename, name);
+       
+       return unlink(filename);
+}
+static inline int OSMOCOM_LINK(const char *oldname, const char *newname)
+{
+       char oldfilename[strlen(OSMOCOM_CONFDIR) + strlen(oldname) + 1];
+       char newfilename[strlen(OSMOCOM_CONFDIR) + strlen(newname) + 1];
+
+       strcpy(oldfilename, OSMOCOM_CONFDIR);
+       strcat(oldfilename, oldname);
+       strcpy(newfilename, OSMOCOM_CONFDIR);
+       strcat(newfilename, newname);
+       return link(oldfilename, newfilename);
+}
+static inline int OSMOCOM_MKSTEMP(char *name)
+{
+       char filename[strlen(OSMOCOM_CONFDIR) + strlen(name) + 1];
+       int rc;
+
+       strcpy(filename, OSMOCOM_CONFDIR);
+       strcat(filename, name);
+       
+       rc = mkstemp(filename);
+
+       memcpy(name + strlen(name) - 6, filename + strlen(filename) - 6, 6);
+
+       return rc;
+}
+static inline int OSMOCOM_CHMOD(const char *name, mode_t mode)
+{
+       char filename[strlen(OSMOCOM_CONFDIR) + strlen(name) + 1];
+
+       strcpy(filename, OSMOCOM_CONFDIR);
+       strcat(filename, name);
+       
+       return chmod(filename, mode);
+}
 
 #endif /* _OSMOCOM_FILE_H */
index 1a4fa9a..3e803a6 100644 (file)
@@ -74,6 +74,7 @@ struct gsm_support {
        /* IMEI */
        char imei[15];
        char imeisv[17];
+       char imei_random;
 
        /* radio */
        int8_t min_rxlev_db;
index f521693..e5c1ce7 100644 (file)
@@ -39,4 +39,6 @@ extern int telnet_init(struct osmocom_ms *ms, int port);
 
 extern int ms_vty_init(struct osmocom_ms *ms);
 
+extern void vty_notify(struct osmocom_ms *ms, const char *fmt, ...);
+
 #endif
index 089f686..1d51755 100644 (file)
@@ -35,6 +35,7 @@
 #include <osmocom/gsmtap_util.h>
 #include <osmocom/logging.h>
 #include <osmocom/telnet_interface.h>
+#include <osmocom/file.h>
 
 #include <osmocore/msgb.h>
 #include <osmocore/talloc.h>
@@ -42,6 +43,7 @@
 #include <osmocore/signal.h>
 
 extern struct log_target *stderr_target;
+static const char *config_file = "osmocom.cfg";
 
 static int started = 0;
 
@@ -87,9 +89,8 @@ static int signal_cb(unsigned int subsys, unsigned int signal,
                ms = signal_data;
                gsm_subscr_testcard(ms, 1, 1, "0000000000");
 //             ms->subscr.plmn_valid = 1;
-               ms->subscr.plmn_mcc = 1;
-               ms->subscr.plmn_mnc = 1;
-               ms->plmn.mode = PLMN_MODE_MANUAL;
+               ms->subscr.plmn_mcc = 262;
+               ms->subscr.plmn_mnc = 2;
                /* start PLMN + cell selection process */
                nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON);
                if (!nmsg)
@@ -137,6 +138,8 @@ int mobile_exit(struct osmocom_ms *ms)
 
 int l23_app_init(struct osmocom_ms *ms)
 {
+       int rc;
+
        log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG");
 
        srand(time(NULL));
@@ -153,6 +156,14 @@ int l23_app_init(struct osmocom_ms *ms)
        l23_app_exit = mobile_exit;
 
        telnet_init(ms, 4242);
+       rc = vty_read_config_file(config_file);
+       if (rc < 0) {
+               fprintf(stderr, "Failed to parse the config file: '%s'\n",
+                       config_file);
+               fprintf(stderr, "Please create config file using: "
+                       "'touch %s%s'\n", OSMOCOM_CONFDIR, config_file);
+               return rc;
+       }
 
        return 0;
 }
index efd1c34..0fc82e1 100755 (executable)
@@ -36,6 +36,7 @@
 #include <osmocom/file.h>
 #include <osmocom/osmocom_data.h>
 #include <osmocom/networks.h>
+#include <osmocom/telnet_interface.h>
 
 extern void *l23_ctx;
 
@@ -709,9 +710,10 @@ static int gsm322_a_go_on_plmn(struct osmocom_ms *ms, struct msgb *msg)
 /* indicate selected PLMN */
 static int gsm322_a_indicate_selected(struct osmocom_ms *ms, struct msgb *msg)
 {
-#ifdef TODO
-       indicate selected plmn to user
-#endif
+       struct gsm322_plmn *plmn = &ms->plmn;
+
+       vty_notify(ms, "Selected Network: %s, %s\n",
+               gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
 
        return gsm322_a_go_on_plmn(ms, msg);
 }
@@ -1155,17 +1157,12 @@ static int gsm322_m_display_plmns(struct osmocom_ms *ms, struct msgb *msg)
        /* generate list */
        gsm322_sort_list(ms);
 
-#ifdef TODO
-       display PLMNs to user
-#else
-       printf("\nSelect from Network:\n");
+       vty_notify(ms, "Select from Network:\n");
 
        llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
-               printf("Network %03d, %02d (%s, %s)\n", temp->mcc, temp->mnc,
-                       gsm_get_mcc(temp->mcc),
+               vty_notify(ms, " Network %03d, %02d (%s, %s)\n", temp->mcc,
+                       temp->mnc, gsm_get_mcc(temp->mcc),
                        gsm_get_mnc(temp->mcc, temp->mnc));
-       printf("\n");
-#endif
        
        /* go Not on PLMN state */
        return gsm322_m_go_not_on_plmn(ms, msg);
@@ -1190,6 +1187,7 @@ static int gsm322_m_user_resel(struct osmocom_ms *ms, struct msgb *msg)
        }
 
        /* initiate search at cell selection */
+       vty_notify(ms, "Searching Network, please wait...\n");
        LOGP(DPLMN, LOGL_INFO, "User re-select, start PLMN search first.\n");
 
        nmsg = gsm322_msgb_alloc(GSM322_EVENT_PLMN_SEARCH_START);
@@ -1240,6 +1238,7 @@ static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg)
 
        /* initiate search at cell selection */
        LOGP(DPLMN, LOGL_INFO, "Switch on, start PLMN search first.\n");
+       vty_notify(ms, "Searching Network, please wait...\n");
 
        nmsg = gsm322_msgb_alloc(GSM322_EVENT_PLMN_SEARCH_START);
        if (!nmsg)
@@ -1309,9 +1308,10 @@ static int gsm322_m_go_on_plmn(struct osmocom_ms *ms, struct msgb *msg)
 /* indicate selected PLMN */
 static int gsm322_m_indicate_selected(struct osmocom_ms *ms, struct msgb *msg)
 {
-#ifdef TODO
-       indicate selected plmn to user
-#endif
+       struct gsm322_plmn *plmn = &ms->plmn;
+
+       vty_notify(ms, "Selected Network: %s, %s\n",
+               gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
 
        return gsm322_m_go_on_plmn(ms, msg);
 }
@@ -1351,6 +1351,8 @@ static int gsm322_m_choose_plmn(struct osmocom_ms *ms, struct msgb *msg)
        plmn->mcc = gm->mcc;
        plmn->mnc = gm->mnc;
 
+       vty_notify(ms, "Selected Network: %s, %s\n",
+               gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
        LOGP(DPLMN, LOGL_INFO, "User selects PLMN. (mcc=%03d mnc=%02d  "
                "%s, %s)\n", plmn->mcc, plmn->mnc,
                gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
@@ -2840,7 +2842,8 @@ static struct plmnmstatelist {
 } plmnmstatelist[] = {
        {SBIT(GSM322_M0_NULL),
         GSM322_EVENT_SWITCH_ON, gsm322_m_switch_on},
-       {SBIT(GSM322_M0_NULL) | SBIT(GSM322_M2_ON_PLMN),
+       {SBIT(GSM322_M0_NULL) | SBIT(GSM322_M3_NOT_ON_PLMN) |
+        SBIT(GSM322_M2_ON_PLMN),
         GSM322_EVENT_PLMN_SEARCH_END, gsm322_m_display_plmns},
        {ALL_STATES,
         GSM322_EVENT_SWITCH_OFF, gsm322_m_switch_off},
@@ -2861,7 +2864,7 @@ static struct plmnmstatelist {
        {SBIT(GSM322_M1_TRYING_RPLMN) | SBIT(GSM322_M2_ON_PLMN) |
         SBIT(GSM322_M4_TRYING_PLMN),
         GSM322_EVENT_INVALID_SIM, gsm322_m_sim_removed},
-       {SBIT(GSM322_M2_ON_PLMN),
+       {SBIT(GSM322_M3_NOT_ON_PLMN) | SBIT(GSM322_M2_ON_PLMN),
         GSM322_EVENT_USER_RESEL, gsm322_m_user_resel},
        {SBIT(GSM322_M3_NOT_ON_PLMN),
         GSM322_EVENT_PLMN_AVAIL, gsm322_m_plmn_avail},
@@ -3072,7 +3075,7 @@ int gsm322_dump_cs_list(struct gsm322_cellsel *cs, uint8_t flags,
                                if (cs->list[i].sysinfo->cell_barr)
                                        print(priv, "low    ");
                                else
-                                       print(priv, "high   ");
+                                       print(priv, "normal ");
                        }
                        for (j = 0; j < 16; j++) {
                                if ((s->class_barr & (1 << j)))
index f671853..5ec71cc 100644 (file)
@@ -263,7 +263,9 @@ int main(int argc, char **argv)
        lapdm_init(&ms->l2_entity.lapdm_dcch, ms);
        lapdm_init(&ms->l2_entity.lapdm_acch, ms);
 
-       l23_app_init(ms);
+       rc = l23_app_init(ms);
+       if (rc < 0)
+               exit(1);
 
        if (bsc_register_fd(&ms->wq.bfd) != 0) {
                fprintf(stderr, "Failed to register fd.\n");
index 3d6a6bd..64507ac 100644 (file)
@@ -66,12 +66,12 @@ void gsm_support_init(struct osmocom_ms *ms)
        sup->a5_6 = 0;
        sup->a5_7 = 0;
        /* radio support */
-       sup->p_gsm = 0; /* P-GSM only */
-       sup->e_gsm = 1; /* E-GSM */
+       sup->p_gsm = 1; /* P-GSM only */
+       sup->e_gsm = 0; /* E-GSM */
        sup->r_gsm = 0; /* R-GSM */
        sup->r_capa = 0;
        sup->low_capa = 4; /* p,e,r power class */
-       sup->dcs_1800 = 1;
+       sup->dcs_1800 = 0;
        /* set supported frequencies */
        if (sup->e_gsm || sup->r_gsm)
                sup->freq_map[0] |= 1;
@@ -113,19 +113,19 @@ void gsm_support_init(struct osmocom_ms *ms)
 
 /* (3.2.1) maximum channels to scan within each band */
 struct gsm_support_scan_max gsm_sup_smax[] = {
-#if 0
        { 259, 293, 15, 0 },
        { 360, 340, 15, 0 },
        { 438, 511, 25, 0 },
        { 128, 251, 30, 0 },
        { 955, 124, 30, 0 },
        { 512, 885, 40, 0 },
-#else
-//     { 955, 125, 1, 0 }, /* we support only one ARFCN */
-#endif
        { 0, 0, 0, 0 }
 };
 
+int gsm_support_random_imei(struct gsm_support *sup)
+{
+}
+
 
 /* dump support */
 void gsm_support_dump(struct gsm_support *sup,
index 0f98a00..bec493c 100644 (file)
@@ -203,3 +203,31 @@ void vty_event(enum event event, int sock, struct vty *vty)
        }
 }
 
+void vty_notify(struct osmocom_ms *ms, const char *fmt, ...)
+{
+       struct telnet_connection *connection;
+       char buffer[1000];
+       va_list args;
+
+       va_start(args, fmt);
+       vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
+       buffer[sizeof(buffer) - 1] = '\0';
+       va_end(args);
+
+       if (!buffer[0])
+               return;
+
+       llist_for_each_entry(connection, &active_connections, entry) {
+               struct vty *vty = connection->vty;
+               if (vty) {
+                       if (buffer[strlen(buffer) - 1] == '\n') {
+                               buffer[strlen(buffer) - 1] = '\0';
+                               vty_out(vty, "%% (MS %s) %s%s", ms->name, 
+                                       buffer, VTY_NEWLINE);
+                               buffer[strlen(buffer)] = '\n';
+                       } else
+                               vty_out(vty, "%% (MS %s) %s", ms->name, buffer);
+               }
+       }
+}
+
index a777ab7..477b011 100644 (file)
@@ -2474,7 +2474,7 @@ DEFUN(config_write_file,
        sprintf(config_file_tmp, "%s.XXXXXX", config_file);
 
        /* Open file to configuration write. */
-       fd = mkstemp(config_file_tmp);
+       fd = OSMOCOM_MKSTEMP(config_file_tmp);
        if (fd < 0) {
                vty_out(vty, "Can't open configuration file %s.%s",
                        config_file_tmp, VTY_NEWLINE);
@@ -2500,48 +2500,48 @@ DEFUN(config_write_file,
                }
        vty_close(file_vty);
 
-       if (unlink(config_file_sav) != 0)
+       if (OSMOCOM_UNLINK(config_file_sav) != 0)
                if (errno != ENOENT) {
                        vty_out(vty,
                                "Can't unlink backup configuration file %s.%s",
                                config_file_sav, VTY_NEWLINE);
                        talloc_free(config_file_sav);
                        talloc_free(config_file_tmp);
-                       unlink(config_file_tmp);
+                       OSMOCOM_UNLINK(config_file_tmp);
                        return CMD_WARNING;
                }
-       if (link(config_file, config_file_sav) != 0) {
+       if (OSMOCOM_LINK(config_file, config_file_sav) != 0) {
                vty_out(vty, "Can't backup old configuration file %s.%s",
                        config_file_sav, VTY_NEWLINE);
                talloc_free(config_file_sav);
                talloc_free(config_file_tmp);
-               unlink(config_file_tmp);
+               OSMOCOM_UNLINK(config_file_tmp);
                return CMD_WARNING;
        }
        sync();
-       if (unlink(config_file) != 0) {
+       if (OSMOCOM_UNLINK(config_file) != 0) {
                vty_out(vty, "Can't unlink configuration file %s.%s",
                        config_file, VTY_NEWLINE);
                talloc_free(config_file_sav);
                talloc_free(config_file_tmp);
-               unlink(config_file_tmp);
+               OSMOCOM_UNLINK(config_file_tmp);
                return CMD_WARNING;
        }
-       if (link(config_file_tmp, config_file) != 0) {
+       if (OSMOCOM_LINK(config_file_tmp, config_file) != 0) {
                vty_out(vty, "Can't save configuration file %s.%s", config_file,
                        VTY_NEWLINE);
                talloc_free(config_file_sav);
                talloc_free(config_file_tmp);
-               unlink(config_file_tmp);
+               OSMOCOM_UNLINK(config_file_tmp);
                return CMD_WARNING;
        }
-       unlink(config_file_tmp);
+       OSMOCOM_UNLINK(config_file_tmp);
        sync();
 
        talloc_free(config_file_sav);
        talloc_free(config_file_tmp);
 
-       if (chmod(config_file, 0666 & ~CONFIGFILE_MASK) != 0) {
+       if (OSMOCOM_CHMOD(config_file, 0666 & ~CONFIGFILE_MASK) != 0) {
                vty_out(vty, "Can't chmod configuration file %s: %s (%d).%s",
                        config_file, strerror(errno), errno, VTY_NEWLINE);
                return CMD_WARNING;
@@ -3405,5 +3405,5 @@ void cmd_init(int terminal)
                install_element(CONFIG_NODE, &no_service_terminal_length_cmd);
 
        }
-       srand(time(NULL));
+//???  srand(time(NULL));
 }
index 30b3c4e..8484d2d 100644 (file)
@@ -77,9 +77,17 @@ DEFUN(show_ms, show_ms_cmd, "show ms",
 {
        struct osmocom_ms *ms;
 
-       llist_for_each_entry(ms, &ms_list, entity)
-               vty_out(vty, " MS: %s  IMEI: %s%s", ms->name, ms->support.imei,
+       llist_for_each_entry(ms, &ms_list, entity) {
+               vty_out(vty, "MS NAME: %s%s", ms->name, VTY_NEWLINE);
+               vty_out(vty, " IMEI: %s%s", ms->support.imei, VTY_NEWLINE);
+               vty_out(vty, " IMEISV: %s%s", ms->support.imeisv, VTY_NEWLINE);
+               vty_out(vty, " IMEI selection: %s%s",
+                       (ms->support.imei_random) ? "random" : "fixed",
                        VTY_NEWLINE);
+               vty_out(vty, " network selection mode: %s%s",
+                       (ms->plmn.mode == PLMN_MODE_AUTO)
+                               ? "automatic" : "manual", VTY_NEWLINE);
+       }
 
        return CMD_SUCCESS;
 }
@@ -233,6 +241,46 @@ DEFUN(remove_sim, remove_sim_cmd, "remove sim MS_NAME",
        return CMD_SUCCESS;
 }
 
+DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
+       "Select ...\nSelect Network\n")
+{
+       struct osmocom_ms *ms;
+       struct msgb *nmsg;
+       struct gsm322_msg *ngm;
+
+       ms = get_ms(argv[0], vty);
+       if (!ms)
+               return CMD_WARNING;
+
+       nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOSE_PLMN);
+       if (!nmsg)
+               return CMD_WARNING;
+       ngm = (struct gsm322_msg *) nmsg->data;
+       ngm->mcc = atoi(argv[1]);
+       ngm->mnc = atoi(argv[2]);
+       gsm322_plmn_sendmsg(ms, nmsg);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(network_search, network_search_cmd, "network search MS_NAME",
+       "Network ...\nTrigger network search\n")
+{
+       struct osmocom_ms *ms;
+       struct msgb *nmsg;
+
+       ms = get_ms(argv[0], vty);
+       if (!ms)
+               return CMD_WARNING;
+
+       nmsg = gsm322_msgb_alloc(GSM322_EVENT_USER_RESEL);
+       if (!nmsg)
+               return CMD_WARNING;
+       gsm322_plmn_sendmsg(ms, nmsg);
+
+       return CMD_SUCCESS;
+}
+
 /* per MS config */
 DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
        "Select a mobile station to configure\n")
@@ -272,6 +320,14 @@ DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
        struct osmocom_ms *ms = vty->index;
        struct msgb *nmsg;
 
+       if (!ms->plmn.state) {
+               if (argv[0][0] == 'a')
+                       ms->plmn.mode = PLMN_MODE_AUTO;
+               else
+                       ms->plmn.mode = PLMN_MODE_MANUAL;
+
+               return CMD_SUCCESS;
+       }
        if (argv[0][0] == 'a')
                nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
        else
@@ -302,6 +358,8 @@ int ms_vty_init(void)
 
        install_element(ENABLE_NODE, &insert_test_cmd);
        install_element(ENABLE_NODE, &remove_sim_cmd);
+       install_element(ENABLE_NODE, &network_search_cmd);
+       install_element(ENABLE_NODE, &network_select_cmd);
 
        install_element(CONFIG_NODE, &cfg_ms_cmd);
        install_node(&ms_node, config_write_ms);