pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/30961 )
Change subject: WIP: VTY ......................................................................
WIP: VTY
Change-Id: Iabfb3129199488d790b89884bc1e424f2aca696f --- A src/host/layer23/include/osmocom/bb/modem/vty.h A src/host/layer23/src/modem/vty.c 2 files changed, 317 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/61/30961/1
diff --git a/src/host/layer23/include/osmocom/bb/modem/vty.h b/src/host/layer23/include/osmocom/bb/modem/vty.h new file mode 100644 index 0000000..d066804 --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/modem/vty.h @@ -0,0 +1,21 @@ +#ifndef OSMOCOM_VTY_H +#define OSMOCOM_VTY_H + +#include <osmocom/bb/common/osmocom_data.h> +#include <osmocom/vty/vty.h> +#include <osmocom/vty/buffer.h> +#include <osmocom/vty/command.h> + +enum ms_vty_node { + MS_NODE = _LAST_OSMOVTY_NODE + 1, + TESTSIM_NODE, + SUPPORT_NODE, + AUDIO_NODE, +}; + +int ms_vty_go_parent(struct vty *vty); +int ms_vty_init(void); +extern void vty_notify(struct osmocom_ms *ms, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + +#endif + diff --git a/src/host/layer23/src/modem/vty.c b/src/host/layer23/src/modem/vty.c new file mode 100644 index 0000000..fbb852d --- /dev/null +++ b/src/host/layer23/src/modem/vty.c @@ -0,0 +1,296 @@ +/* + * (C) 2010 by Andreas Eversberg jolly@eversberg.eu + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <sys/types.h> + +#include <osmocom/core/utils.h> +#include <osmocom/gsm/gsm48.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/signal.h> +#include <osmocom/crypt/auth.h> + +#include <osmocom/bb/common/osmocom_data.h> +#include <osmocom/bb/common/networks.h> +#include <osmocom/bb/common/gps.h> +#include <osmocom/bb/mobile/mncc.h> +#include <osmocom/bb/mobile/mncc_ms.h> +#include <osmocom/bb/mobile/transaction.h> +#include <osmocom/bb/mobile/vty.h> +#include <osmocom/bb/mobile/app_mobile.h> +#include <osmocom/bb/mobile/gsm480_ss.h> +#include <osmocom/bb/mobile/gsm411_sms.h> +#include <osmocom/vty/telnet_interface.h> +#include <osmocom/vty/misc.h> + +extern struct llist_head ms_list; +extern struct llist_head active_connections; + +struct cmd_node ms_node = { + MS_NODE, + "%s(ms)# ", + 1 +}; + +struct cmd_node testsim_node = { + TESTSIM_NODE, + "%s(test-sim)# ", + 1 +}; + +struct cmd_node support_node = { + SUPPORT_NODE, + "%s(support)# ", + 1 +}; + +struct cmd_node audio_node = { + AUDIO_NODE, + "%s(audio)# ", + 1 +}; + +static void print_vty(void *priv, const char *fmt, ...) +{ + char buffer[1000]; + struct vty *vty = priv; + 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]) { + if (buffer[strlen(buffer) - 1] == '\n') { + buffer[strlen(buffer) - 1] = '\0'; + vty_out(vty, "%s%s", buffer, VTY_NEWLINE); + } else + vty_out(vty, "%s", buffer); + } +} + +int vty_check_number(struct vty *vty, const char *number) +{ + int i; + + for (i = 0; i < strlen(number); i++) { + /* allow international notation with + */ + if (i == 0 && number[i] == '+') + continue; + if (!(number[i] >= '0' && number[i] <= '9') + && number[i] != '*' + && number[i] != '#' + && !(number[i] >= 'a' && number[i] <= 'c')) { + vty_out(vty, "Invalid digit '%c' of number!%s", + number[i], VTY_NEWLINE); + return -EINVAL; + } + } + if (number[0] == '\0' || (number[0] == '+' && number[1] == '\0')) { + vty_out(vty, "Given number has no digits!%s", VTY_NEWLINE); + return -EINVAL; + } + + return 0; +} + +int vty_reading = 0; +static int hide_default = 0; + +static void vty_restart(struct vty *vty, struct osmocom_ms *ms) +{ + if (vty_reading) + return; + if (ms->shutdown != MS_SHUTDOWN_NONE) + return; + vty_out(vty, "You must restart MS '%s' ('shutdown / no shutdown') for " + "change to take effect!%s", ms->name, VTY_NEWLINE); +} + +static void vty_restart_if_started(struct vty *vty, struct osmocom_ms *ms) +{ + if (!ms->started) + return; + vty_restart(vty, ms); +} + +static struct osmocom_ms *get_ms(const char *name, struct vty *vty) +{ + struct osmocom_ms *ms; + + llist_for_each_entry(ms, &ms_list, entity) { + if (!strcmp(ms->name, name)) { + if (ms->shutdown != MS_SHUTDOWN_NONE) { + vty_out(vty, "MS '%s' is admin down.%s", name, + VTY_NEWLINE); + return NULL; + } + return ms; + } + } + vty_out(vty, "MS name '%s' does not exits.%s", name, VTY_NEWLINE); + + return NULL; +} + +static void gsm_ms_dump(struct osmocom_ms *ms, struct vty *vty) +{ + struct gsm_settings *set = &ms->settings; + struct gsm_trans *trans; + char *service = ""; + + if (!ms->started) + service = ", radio is not started"; + else if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE) { + /* current MM idle state */ + switch (ms->mmlayer.substate) { + case GSM48_MM_SST_NORMAL_SERVICE: + case GSM48_MM_SST_PLMN_SEARCH_NORMAL: + service = ", service is normal"; + break; + case GSM48_MM_SST_LOC_UPD_NEEDED: + case GSM48_MM_SST_ATTEMPT_UPDATE: + service = ", service is limited (pending)"; + break; + case GSM48_MM_SST_NO_CELL_AVAIL: + service = ", service is unavailable"; + break; + default: + if (ms->subscr.sim_valid) + service = ", service is limited"; + else + service = ", service is limited " + "(IMSI detached)"; + break; + } + } else + service = ", MM connection active"; + + vty_out(vty, "MS '%s' is %s%s%s%s", ms->name, + (ms->shutdown != MS_SHUTDOWN_NONE) ? "administratively " : "", + (ms->shutdown != MS_SHUTDOWN_NONE || !ms->started) ? "down" : "up", + (ms->shutdown == MS_SHUTDOWN_NONE) ? service : "", + VTY_NEWLINE); + vty_out(vty, " IMEI: %s%s", set->imei, VTY_NEWLINE); + vty_out(vty, " IMEISV: %s%s", set->imeisv, VTY_NEWLINE); + if (set->imei_random) + vty_out(vty, " IMEI generation: random (%d trailing " + "digits)%s", set->imei_random, VTY_NEWLINE); + else + vty_out(vty, " IMEI generation: fixed%s", VTY_NEWLINE); + + if (ms->shutdown != MS_SHUTDOWN_NONE) + return; + + if (set->plmn_mode == PLMN_MODE_AUTO) + vty_out(vty, " automatic network selection state: %s%s", + get_a_state_name(ms->plmn.state), VTY_NEWLINE); + else + vty_out(vty, " manual network selection state : %s%s", + get_m_state_name(ms->plmn.state), VTY_NEWLINE); + if (ms->plmn.mcc) + vty_out(vty, " MCC=%s " + "MNC=%s (%s, %s)%s", gsm_print_mcc(ms->plmn.mcc), + gsm_print_mnc(ms->plmn.mnc), gsm_get_mcc(ms->plmn.mcc), + gsm_get_mnc(ms->plmn.mcc, ms->plmn.mnc), VTY_NEWLINE); + vty_out(vty, " cell selection state: %s%s", + get_cs_state_name(ms->cellsel.state), VTY_NEWLINE); + if (ms->cellsel.sel_mcc) { + vty_out(vty, " ARFCN=%s MCC=%s MNC=%s " + "LAC=0x%04x CELLID=0x%04x%s", + gsm_print_arfcn(ms->cellsel.sel_arfcn), + gsm_print_mcc(ms->cellsel.sel_mcc), + gsm_print_mnc(ms->cellsel.sel_mnc), + ms->cellsel.sel_lac, ms->cellsel.sel_id, VTY_NEWLINE); + vty_out(vty, " (%s, %s)%s", + gsm_get_mcc(ms->cellsel.sel_mcc), + gsm_get_mnc(ms->cellsel.sel_mcc, ms->cellsel.sel_mnc), + VTY_NEWLINE); + } + vty_out(vty, " radio resource layer state: %s%s", + gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE); + vty_out(vty, " mobility management layer state: %s", + gsm48_mm_state_names[ms->mmlayer.state]); + if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE) + vty_out(vty, ", %s", + gsm48_mm_substate_names[ms->mmlayer.substate]); + vty_out(vty, "%s", VTY_NEWLINE); + llist_for_each_entry(trans, &ms->trans_list, entry) { + vty_out(vty, " call control state: %s%s", + gsm48_cc_state_name(trans->cc.state), VTY_NEWLINE); + } +} + + +DEFUN(show_ms, show_ms_cmd, "show ms [MS_NAME]", + SHOW_STR "Display available MS entities\n") +{ + struct osmocom_ms *ms; + + if (argc) { + llist_for_each_entry(ms, &ms_list, entity) { + if (!strcmp(ms->name, argv[0])) { + gsm_ms_dump(ms, vty); + return CMD_SUCCESS; + } + } + vty_out(vty, "MS name '%s' does not exits.%s", argv[0], + VTY_NEWLINE); + return CMD_WARNING; + } else { + llist_for_each_entry(ms, &ms_list, entity) { + gsm_ms_dump(ms, vty); + vty_out(vty, "%s", VTY_NEWLINE); + } + } + + return CMD_SUCCESS; +} + +int ms_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MS_NODE: + vty->node = CONFIG_NODE; + vty->index = NULL; + break; + case TESTSIM_NODE: + case SUPPORT_NODE: + case AUDIO_NODE: + vty->node = MS_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + + return vty->node; +} + +int ms_vty_init(void) +{ + install_element_ve(&show_ms_cmd); + + /* Register the talloc context introspection command */ + osmo_talloc_vty_add_cmds(); + + return 0; +} +