2655 lines
73 KiB
C
2655 lines
73 KiB
C
/*
|
|
* (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/gsm/gsm23003.h>
|
|
|
|
#include <osmocom/bb/common/osmocom_data.h>
|
|
#include <osmocom/bb/common/ms.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/bb/mobile/gsm44068_gcc_bcc.h>
|
|
#include <osmocom/vty/telnet_interface.h>
|
|
#include <osmocom/vty/misc.h>
|
|
|
|
struct cmd_node support_node = {
|
|
SUPPORT_NODE,
|
|
"%s(support)# ",
|
|
1
|
|
};
|
|
|
|
struct cmd_node audio_node = {
|
|
AUDIO_NODE,
|
|
"%s(audio)# ",
|
|
1
|
|
};
|
|
|
|
struct cmd_node vgcs_node = {
|
|
VGCS_NODE,
|
|
"%s(group-call)# ",
|
|
1
|
|
};
|
|
|
|
struct cmd_node vbs_node = {
|
|
VBS_NODE,
|
|
"%s(broadcast-call)# ",
|
|
1
|
|
};
|
|
|
|
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_check_callref(struct vty *vty, const char *number)
|
|
{
|
|
int i, ii = strlen(number);
|
|
|
|
/* First check digits, so that a false command result the following error message. */
|
|
for (i = 0; i < ii; i++) {
|
|
if (!(number[i] >= '0' && number[i] <= '9')) {
|
|
vty_out(vty, "Invalid digit '%c' in callref!%s",
|
|
number[i], VTY_NEWLINE);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
if (ii < 1) {
|
|
vty_out(vty, "Given callref has no digits!%s", VTY_NEWLINE);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (ii > 8) {
|
|
vty_out(vty, "Given callref is too long!%s", VTY_NEWLINE);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void vty_restart(struct vty *vty, struct osmocom_ms *ms)
|
|
{
|
|
if (l23_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 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.plmn.mcc)
|
|
vty_out(vty, " MCC=%s "
|
|
"MNC=%s (%s, %s)%s", osmo_mcc_name(ms->plmn.plmn.mcc),
|
|
osmo_mnc_name(ms->plmn.plmn.mnc, ms->plmn.plmn.mnc_3_digits),
|
|
gsm_get_mcc(ms->plmn.plmn.mcc),
|
|
gsm_get_mnc(&ms->plmn.plmn), VTY_NEWLINE);
|
|
vty_out(vty, " cell selection state: %s%s",
|
|
get_cs_state_name(ms->cellsel.state), VTY_NEWLINE);
|
|
if (ms->cellsel.sel_cgi.lai.plmn.mcc) {
|
|
vty_out(vty, " ARFCN=%s CGI=%s%s",
|
|
gsm_print_arfcn(ms->cellsel.sel_arfcn),
|
|
osmo_cgi_name(&ms->cellsel.sel_cgi), VTY_NEWLINE);
|
|
vty_out(vty, " (%s, %s)%s",
|
|
gsm_get_mcc(ms->cellsel.sel_cgi.lai.plmn.mcc),
|
|
gsm_get_mnc(&ms->cellsel.sel_cgi.lai.plmn),
|
|
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"
|
|
"Display specific MS with given name")
|
|
{
|
|
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;
|
|
}
|
|
|
|
llist_for_each_entry(ms, &ms_list, entity) {
|
|
gsm_ms_dump(ms, vty);
|
|
vty_out(vty, "%s", VTY_NEWLINE);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
|
|
SHOW_STR "Display information about received cells\n"
|
|
"Name of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SUPPORT, l23_vty_printf,
|
|
vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023> [pcs]",
|
|
SHOW_STR "Display information about received cell\n"
|
|
"Name of MS (see \"show ms\")\nRadio frequency number\n"
|
|
"Given frequency is PCS band (1900) rather than DCS band.")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct gsm48_sysinfo *s;
|
|
uint16_t arfcn = atoi(argv[1]);
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
if (argc > 2) {
|
|
if (arfcn < 512 || arfcn > 810) {
|
|
vty_out(vty, "Given ARFCN not in PCS band%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
arfcn |= ARFCN_PCS;
|
|
}
|
|
|
|
s = ms->cellsel.list[arfcn2index(arfcn)].sysinfo;
|
|
if (!s) {
|
|
vty_out(vty, "Given ARFCN '%s' has no sysinfo available%s",
|
|
argv[1], VTY_NEWLINE);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
gsm48_sysinfo_dump(s, arfcn, l23_vty_printf, vty, ms->settings.freq_map);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_nbcells, show_nbcells_cmd, "show neighbour-cells MS_NAME",
|
|
SHOW_STR "Display information about current neighbour cells\n"
|
|
"Name of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm322_dump_nb_list(&ms->cellsel, l23_vty_printf, vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [MCC] [MNC]",
|
|
SHOW_STR "Display information about band allocations\n"
|
|
"Name of MS (see \"show ms\")\nMobile Country Code\n"
|
|
"Mobile Network Code")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct osmo_plmn_id plmn;
|
|
struct osmo_plmn_id *plmn_ptr = NULL;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
if (argc >= 3) {
|
|
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
|
|
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
|
|
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
plmn_ptr = &plmn;
|
|
}
|
|
|
|
gsm322_dump_ba_list(&ms->cellsel, plmn_ptr, l23_vty_printf, vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_forb_plmn, show_forb_plmn_cmd, "show forbidden plmn MS_NAME",
|
|
SHOW_STR "Display information about forbidden cells / networks\n"
|
|
"Display forbidden PLMNs\nName of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm_subscr_dump_forbidden_plmn(ms, l23_vty_printf, vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_forb_la, show_forb_la_cmd, "show forbidden location-area MS_NAME",
|
|
SHOW_STR "Display information about forbidden cells / networks\n"
|
|
"Display forbidden location areas\nName of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm322_dump_forbidden_la(ms, l23_vty_printf, vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
#define SHOW_ASCI_STR SHOW_STR "Display information about ASCI items\nName of MS (see \"show ms\")\n"
|
|
|
|
DEFUN(show_asci_calls, show_asci_calls_cmd, "show asci MS_NAME calls",
|
|
SHOW_ASCI_STR "Display ongoing ASCI calls")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm44068_dump_calls(ms, l23_vty_printf, vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(show_asci_neighbors, show_asci_neighbors_cmd, "show asci MS_NAME neighbors",
|
|
SHOW_ASCI_STR "Display neigbor cells of ongoing or last ASCI call")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm48_si10_dump(ms->cellsel.si, l23_vty_printf, vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(monitor_network, monitor_network_cmd, "monitor network MS_NAME",
|
|
"Monitor...\nMonitor network information\nName of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm48_rr_start_monitor(ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(no_monitor_network, no_monitor_network_cmd, "no monitor network MS_NAME",
|
|
NO_STR "Monitor...\nDeactivate monitor of network information\n"
|
|
"Name of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
gsm48_rr_stop_monitor(ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(network_select, network_select_cmd,
|
|
"network select MS_NAME MCC MNC [force]",
|
|
"Select ...\nSelect Network\nName of MS (see \"show ms\")\n"
|
|
"Mobile Country Code\nMobile Network Code\n"
|
|
"Force selecting a network that is not in the list")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct gsm322_plmn *plmn322;
|
|
struct msgb *nmsg;
|
|
struct gsm322_msg *ngm;
|
|
struct gsm322_plmn_list *temp;
|
|
struct osmo_plmn_id plmn;
|
|
int found = 0;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
plmn322 = &ms->plmn;
|
|
|
|
if (ms->settings.plmn_mode != PLMN_MODE_MANUAL) {
|
|
vty_out(vty, "Not in manual network selection mode%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
|
|
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
|
|
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (argc < 4) {
|
|
llist_for_each_entry(temp, &plmn322->sorted_plmn, entry)
|
|
if (osmo_plmn_cmp(&temp->plmn, &plmn) == 0)
|
|
found = 1;
|
|
if (!found) {
|
|
vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
|
|
vty_out(vty, "To force selecting this network, use "
|
|
"'force' keyword%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOOSE_PLMN);
|
|
if (!nmsg)
|
|
return CMD_WARNING;
|
|
ngm = (struct gsm322_msg *) nmsg->data;
|
|
memcpy(&ngm->plmn, &plmn, sizeof(struct osmo_plmn_id));
|
|
gsm322_plmn_sendmsg(ms, nmsg);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup|hold)",
|
|
"Make a call\nName of MS (see \"show ms\")\nPhone number to call "
|
|
"(Use digits '0123456789*#abc', and '+' to dial international)\n"
|
|
"Make an emergency call\nAnswer an incoming call\nHangup a call\n"
|
|
"Hold current active call\n")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct gsm_settings *set;
|
|
struct gsm_settings_abbrev *abbrev;
|
|
char *number;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
set = &ms->settings;
|
|
|
|
if (set->ch_cap == GSM_CAP_SDCCH) {
|
|
vty_out(vty, "Basic call is not supported for SDCCH only "
|
|
"mobile%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
number = (char *)argv[1];
|
|
if (!strcmp(number, "emergency"))
|
|
mncc_call(ms, number);
|
|
else if (!strcmp(number, "answer"))
|
|
mncc_answer(ms);
|
|
else if (!strcmp(number, "hangup"))
|
|
mncc_hangup(ms);
|
|
else if (!strcmp(number, "hold"))
|
|
mncc_hold(ms);
|
|
else {
|
|
llist_for_each_entry(abbrev, &set->abbrev, list) {
|
|
if (!strcmp(number, abbrev->abbrev)) {
|
|
number = abbrev->number;
|
|
vty_out(vty, "Dialing number '%s'%s", number,
|
|
VTY_NEWLINE);
|
|
break;
|
|
}
|
|
}
|
|
if (vty_check_number(vty, number))
|
|
return CMD_WARNING;
|
|
mncc_call(ms, number);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(call_retr, call_retr_cmd, "call MS_NAME retrieve [NUMBER]",
|
|
"Make a call\nName of MS (see \"show ms\")\n"
|
|
"Retrieve call on hold\nNumber of call to retrieve")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
mncc_retrieve(ms, (argc > 1) ? atoi(argv[1]) : 0);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(call_dtmf, call_dtmf_cmd, "call MS_NAME dtmf DIGITS",
|
|
"Make a call\nName of MS (see \"show ms\")\n"
|
|
"One or more DTMF digits to transmit")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct gsm_settings *set;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
set = &ms->settings;
|
|
|
|
if (!set->cc_dtmf) {
|
|
vty_out(vty, "DTMF not supported, please enable!%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
mncc_dtmf(ms, (char *)argv[1]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(sms, sms_cmd, "sms MS_NAME NUMBER .LINE",
|
|
"Send an SMS\nName of MS (see \"show ms\")\nPhone number to send SMS "
|
|
"(Use digits '0123456789*#abc', and '+' to dial international)\n"
|
|
"SMS text\n")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct gsm_settings *set;
|
|
struct gsm_settings_abbrev *abbrev;
|
|
char *number, *sms_sca = NULL;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
set = &ms->settings;
|
|
|
|
if (!set->sms_ptp) {
|
|
vty_out(vty, "SMS not supported by this mobile, please enable "
|
|
"SMS support%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (ms->subscr.sms_sca[0])
|
|
sms_sca = ms->subscr.sms_sca;
|
|
else if (set->sms_sca[0])
|
|
sms_sca = set->sms_sca;
|
|
|
|
if (!sms_sca) {
|
|
vty_out(vty, "SMS sms-service-center not defined on SIM card, "
|
|
"please define one at settings.%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
number = (char *)argv[1];
|
|
llist_for_each_entry(abbrev, &set->abbrev, list) {
|
|
if (!strcmp(number, abbrev->abbrev)) {
|
|
number = abbrev->number;
|
|
vty_out(vty, "Using number '%s'%s", number,
|
|
VTY_NEWLINE);
|
|
break;
|
|
}
|
|
}
|
|
if (vty_check_number(vty, number))
|
|
return CMD_WARNING;
|
|
|
|
sms_send(ms, sms_sca, number, argv_concat(argv, argc, 2), 42);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(service, service_cmd, "service MS_NAME (*#06#|*#21#|*#67#|*#61#|*#62#"
|
|
"|*#002#|*#004#|*xx*number#|*xx#|#xx#|##xx#|STRING|hangup)",
|
|
"Send a Supplementary Service request\nName of MS (see \"show ms\")\n"
|
|
"Query IMSI\n"
|
|
"Query Call Forwarding Unconditional (CFU)\n"
|
|
"Query Call Forwarding when Busy (CFB)\n"
|
|
"Query Call Forwarding when No Response (CFNR)\n"
|
|
"Query Call Forwarding when Not Reachable\n"
|
|
"Query all Call Forwardings\n"
|
|
"Query all conditional Call Forwardings\n"
|
|
"Set and activate Call Forwarding (xx = Service Code, see above)\n"
|
|
"Activate Call Forwarding (xx = Service Code, see above)\n"
|
|
"Deactivate Call Forwarding (xx = Service Code, see above)\n"
|
|
"Erase and deactivate Call Forwarding (xx = Service Code, see above)\n"
|
|
"Service string "
|
|
"(Example: '*100#' requests account balace on some networks.)\n"
|
|
"Hangup existing service connection")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
ss_send(ms, argv[1], 0);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
#define VGCS_STR "Make a voice group call\nName of MS (see \"show ms\")\n"
|
|
#define VGCS_CMDS "(CALLREF|hangup|leave|talk|listen)"
|
|
#define VGCS_CMDS_TXT \
|
|
"Voice group to call or join\nHangup voice group call\nLeave voice group call\nBecome talker\nBecome listener"
|
|
|
|
/* This command enters VGCS call node with given MS. */
|
|
DEFUN(vgcs_enter, vgcs_enter_cmd, "group-call MS_NAME",
|
|
VGCS_STR)
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
vty->index = ms;
|
|
vty->node = VGCS_NODE;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* These commands perform VGCS on VGCS node. */
|
|
DEFUN(vgcs, vgcs_cmd, VGCS_CMDS,
|
|
VGCS_CMDS_TXT)
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set;
|
|
const char *command;
|
|
|
|
set = &ms->settings;
|
|
|
|
if (!set->vgcs) {
|
|
vty_out(vty, "VGCS not supported by this mobile, please enable VGCS support%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (set->ch_cap == GSM_CAP_SDCCH) {
|
|
vty_out(vty, "ASCI call is not supported for SDCCH only mobile%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
command = (char *)argv[0];
|
|
if (!strcmp(command, "hangup"))
|
|
gcc_bcc_hangup(ms);
|
|
else if (!strcmp(command, "leave"))
|
|
gcc_leave(ms);
|
|
else if (!strcmp(command, "talk"))
|
|
gcc_talk(ms);
|
|
else if (!strcmp(command, "listen"))
|
|
gcc_listen(ms);
|
|
else {
|
|
if (vty_check_callref(vty, command))
|
|
return CMD_WARNING;
|
|
gcc_bcc_call(ms, GSM48_PDISC_GROUP_CC, command);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* These commands perform VGCS on given MS without entering the VGCS node. */
|
|
DEFUN(vgcs_direct, vgcs_direct_cmd, "group-call MS_NAME " VGCS_CMDS,
|
|
VGCS_STR VGCS_CMDS_TXT)
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
vty->index = ms;
|
|
return vgcs(self, vty, argc - 1, argv + 1);
|
|
}
|
|
|
|
#define VBS_STR "Make a voice broadcast call\nName of MS (see \"show ms\")\n"
|
|
#define VBS_CMDS "(CALLREF|hangup)"
|
|
#define VBS_CMDS_TXT \
|
|
"Voice broadcast to call or join\nHangup voice broadcast call"
|
|
|
|
/* This command enters VBS call node with given MS. */
|
|
DEFUN(vbs_enter, vbs_enter_cmd, "broadcast-call MS_NAME",
|
|
VBS_STR)
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
vty->index = ms;
|
|
vty->node = VBS_NODE;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* These commands perform VBS on VBS node. */
|
|
DEFUN(vbs, vbs_cmd, VBS_CMDS,
|
|
VBS_CMDS_TXT)
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set;
|
|
const char *command;
|
|
|
|
set = &ms->settings;
|
|
|
|
if (!set->vbs) {
|
|
vty_out(vty, "VBS not supported by this mobile, please enable VBS support%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (set->ch_cap == GSM_CAP_SDCCH) {
|
|
vty_out(vty, "ASCI call is not supported for SDCCH only mobile%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
command = (char *)argv[0];
|
|
if (!strcmp(command, "hangup"))
|
|
gcc_bcc_hangup(ms);
|
|
else {
|
|
if (vty_check_callref(vty, command))
|
|
return CMD_WARNING;
|
|
gcc_bcc_call(ms, GSM48_PDISC_BCAST_CC, command);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* These commands perform VBS on given MS without entering the VBS node. */
|
|
DEFUN(vbs_direct, vbs_direct_cmd, "broadcast-call MS_NAME " VBS_CMDS,
|
|
VBS_STR VBS_CMDS_TXT)
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
vty->index = ms;
|
|
return vbs(self, vty, argc - 1, argv + 1);
|
|
}
|
|
|
|
#define TEST_CMD_DESC "Special commands for testing\n"
|
|
|
|
DEFUN(test_reselection, test_reselection_cmd, "test re-selection NAME",
|
|
TEST_CMD_DESC "Manually trigger cell re-selection\n"
|
|
"Name of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct gsm_settings *set;
|
|
struct msgb *nmsg;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
set = &ms->settings;
|
|
|
|
if (set->stick) {
|
|
vty_out(vty, "Cannot trigger cell re-selection, because we "
|
|
"stick to a cell!%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_RESEL);
|
|
if (!nmsg)
|
|
return CMD_WARNING;
|
|
gsm322_c_event(ms, nmsg);
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(delete_forbidden_plmn, delete_forbidden_plmn_cmd,
|
|
"delete forbidden plmn NAME MCC MNC",
|
|
"Delete\nForbidden\nplmn\nName of MS (see \"show ms\")\n"
|
|
"Mobile Country Code\nMobile Network Code")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct osmo_plmn_id plmn;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
|
|
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
|
|
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
|
|
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
gsm_subscr_del_forbidden_plmn(&ms->subscr, &plmn);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(network_show, network_show_cmd, "network show MS_NAME",
|
|
"Network ...\nShow results of network search (again)\n"
|
|
"Name of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct gsm_settings *set;
|
|
struct gsm322_plmn *plmn;
|
|
struct gsm322_plmn_list *temp;
|
|
|
|
ms = l23_vty_get_ms(argv[0], vty);
|
|
if (!ms)
|
|
return CMD_WARNING;
|
|
set = &ms->settings;
|
|
plmn = &ms->plmn;
|
|
|
|
if (set->plmn_mode != PLMN_MODE_AUTO
|
|
&& plmn->state != GSM322_M3_NOT_ON_PLMN) {
|
|
vty_out(vty, "Start network search first!%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
|
|
vty_out(vty, " Network %s, %s (%s, %s)%s",
|
|
osmo_mcc_name(temp->plmn.mcc),
|
|
osmo_mnc_name(temp->plmn.mnc, temp->plmn.mnc_3_digits),
|
|
gsm_get_mcc(temp->plmn.mcc),
|
|
gsm_get_mnc(&temp->plmn), VTY_NEWLINE);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(network_search, network_search_cmd, "network search MS_NAME",
|
|
"Network ...\nTrigger network search\nName of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
struct msgb *nmsg;
|
|
|
|
ms = l23_vty_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;
|
|
}
|
|
|
|
DEFUN(cfg_gps_enable, cfg_gps_enable_cmd, "gps enable",
|
|
"GPS receiver")
|
|
{
|
|
if (osmo_gps_open()) {
|
|
g.enable = 1;
|
|
vty_out(vty, "Failed to open GPS device!%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
g.enable = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_gps_enable, cfg_no_gps_enable_cmd, "no gps enable",
|
|
NO_STR "Disable GPS receiver")
|
|
{
|
|
if (g.enable)
|
|
osmo_gps_close();
|
|
g.enable = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
#ifdef _HAVE_GPSD
|
|
DEFUN(cfg_gps_host, cfg_gps_host_cmd, "gps host HOST:PORT",
|
|
"GPS receiver\nSelect gpsd host and port\n"
|
|
"IP and port (optional) of the host running gpsd")
|
|
{
|
|
char* colon = strstr(argv[0], ":");
|
|
if (colon != NULL) {
|
|
memcpy(g.gpsd_host, argv[0], colon - argv[0]);
|
|
g.gpsd_host[colon - argv[0]] = '\0';
|
|
memcpy(g.gpsd_port, colon+1, strlen(colon+1));
|
|
g.gpsd_port[strlen(colon+1)] = '\0';
|
|
} else {
|
|
snprintf(g.gpsd_host, ARRAY_SIZE(g.gpsd_host), "%s", argv[0]);
|
|
g.gpsd_host[ARRAY_SIZE(g.gpsd_host) - 1] = '\0';
|
|
snprintf(g.gpsd_port, ARRAY_SIZE(g.gpsd_port), "2947");
|
|
g.gpsd_port[ARRAY_SIZE(g.gpsd_port) - 1] = '\0';
|
|
}
|
|
g.gps_type = GPS_TYPE_GPSD;
|
|
if (g.enable) {
|
|
osmo_gps_close();
|
|
if (osmo_gps_open()) {
|
|
vty_out(vty, "Failed to connect to gpsd host!%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
DEFUN(cfg_gps_device, cfg_gps_device_cmd, "gps device DEVICE",
|
|
"GPS receiver\nSelect serial device\n"
|
|
"Full path of serial device including /dev/")
|
|
{
|
|
osmo_strlcpy(g.device, argv[0], sizeof(g.device));
|
|
g.device[sizeof(g.device) - 1] = '\0';
|
|
g.gps_type = GPS_TYPE_SERIAL;
|
|
if (g.enable) {
|
|
osmo_gps_close();
|
|
if (osmo_gps_open()) {
|
|
vty_out(vty, "Failed to open GPS device!%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_gps_baud, cfg_gps_baud_cmd, "gps baudrate "
|
|
"(default|4800|""9600|19200|38400|57600|115200)",
|
|
"GPS receiver\nSelect baud rate\nDefault, don't modify\n\n\n\n\n\n")
|
|
{
|
|
if (argv[0][0] == 'd')
|
|
g.baud = 0;
|
|
else
|
|
g.baud = atoi(argv[0]);
|
|
if (g.enable) {
|
|
osmo_gps_close();
|
|
if (osmo_gps_open()) {
|
|
g.enable = 0;
|
|
vty_out(vty, "Failed to open GPS device!%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* per MS config */
|
|
DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
|
|
"Select a mobile station to configure\nName of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
int found = 0;
|
|
|
|
llist_for_each_entry(ms, &ms_list, entity) {
|
|
if (!strcmp(ms->name, argv[0])) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
if (!l23_vty_reading) {
|
|
vty_out(vty, "MS name '%s' does not exits, try "
|
|
"'ms %s create'%s", argv[0], argv[0],
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
ms = mobile_new((char *)argv[0]);
|
|
if (!ms) {
|
|
vty_out(vty, "Failed to add MS name '%s'%s", argv[0],
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
vty->index = ms;
|
|
vty->node = MS_NODE;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_create, cfg_ms_create_cmd, "ms MS_NAME create",
|
|
"Select a mobile station to configure\nName of MS (see \"show ms\")\n"
|
|
"Create if MS does not exists")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
int found = 0;
|
|
|
|
llist_for_each_entry(ms, &ms_list, entity) {
|
|
if (!strcmp(ms->name, argv[0])) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
ms = mobile_new((char *)argv[0]);
|
|
if (!ms) {
|
|
vty_out(vty, "Failed to add MS name '%s'%s", argv[0],
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
vty->index = ms;
|
|
vty->node = MS_NODE;
|
|
|
|
vty_out(vty, "MS '%s' created, after configuration, do 'no shutdown'%s",
|
|
argv[0], VTY_NEWLINE);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_rename, cfg_ms_rename_cmd, "ms MS_NAME rename MS_NAME",
|
|
"Select a mobile station to configure\nName of MS (see \"show ms\")\n"
|
|
"Rename MS\nNew name of MS")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
int found = 0;
|
|
|
|
llist_for_each_entry(ms, &ms_list, entity) {
|
|
if (!strcmp(ms->name, argv[0])) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
vty_out(vty, "MS name '%s' does not exist%s", argv[0],
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
osmo_talloc_replace_string(ms, &ms->name, argv[1]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_ms, cfg_no_ms_cmd, "no ms MS_NAME",
|
|
NO_STR "Select a mobile station to remove\n"
|
|
"Name of MS (see \"show ms\")")
|
|
{
|
|
struct osmocom_ms *ms;
|
|
int found = 0;
|
|
|
|
llist_for_each_entry(ms, &ms_list, entity) {
|
|
if (!strcmp(ms->name, argv[0])) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
vty_out(vty, "MS name '%s' does not exist%s", argv[0],
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
mobile_delete(ms, 1);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
#define SUP_WRITE(item, cmd) \
|
|
if (sup->item) \
|
|
if (!l23_vty_hide_default || !set->item) \
|
|
vty_out(vty, " %s%s%s", (set->item) ? "" : "no ", \
|
|
cmd, VTY_NEWLINE);
|
|
|
|
static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
|
|
{
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_support *sup = &ms->support;
|
|
struct gsm_settings_abbrev *abbrev;
|
|
|
|
vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
|
|
|
|
l23_vty_config_write_ms_node_contents(vty, ms, " ");
|
|
|
|
vty_out(vty, " sap-socket %s%s", set->sap_socket_path, VTY_NEWLINE);
|
|
vty_out(vty, " mncc-socket %s%s", set->mncc_socket_path, VTY_NEWLINE);
|
|
switch (set->mncc_handler) {
|
|
case MNCC_HANDLER_INTERNAL:
|
|
vty_out(vty, " mncc-handler internal%s", VTY_NEWLINE);
|
|
break;
|
|
case MNCC_HANDLER_EXTERNAL:
|
|
vty_out(vty, " mncc-handler external%s", VTY_NEWLINE);
|
|
break;
|
|
case MNCC_HANDLER_DUMMY:
|
|
vty_out(vty, " mncc-handler dummy%s", VTY_NEWLINE);
|
|
}
|
|
vty_out(vty, " network-selection-mode %s%s", (set->plmn_mode
|
|
== PLMN_MODE_AUTO) ? "auto" : "manual", VTY_NEWLINE);
|
|
if (set->emergency_imsi[0])
|
|
vty_out(vty, " emergency-imsi %s%s", set->emergency_imsi,
|
|
VTY_NEWLINE);
|
|
else
|
|
if (!l23_vty_hide_default)
|
|
vty_out(vty, " no emergency-imsi%s", VTY_NEWLINE);
|
|
if (set->sms_sca[0])
|
|
vty_out(vty, " sms-service-center %s%s", set->sms_sca,
|
|
VTY_NEWLINE);
|
|
else
|
|
if (!l23_vty_hide_default)
|
|
vty_out(vty, " no sms-service-center%s", VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->cw)
|
|
vty_out(vty, " %scall-waiting%s", (set->cw) ? "" : "no ",
|
|
VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->auto_answer)
|
|
vty_out(vty, " %sauto-answer%s",
|
|
(set->auto_answer) ? "" : "no ", VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->force_rekey)
|
|
vty_out(vty, " %sforce-rekey%s",
|
|
(set->force_rekey) ? "" : "no ", VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->clip)
|
|
vty_out(vty, " %sclip%s", (set->clip) ? "" : "no ",
|
|
VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->clir)
|
|
vty_out(vty, " %sclir%s", (set->clir) ? "" : "no ",
|
|
VTY_NEWLINE);
|
|
if (set->alter_tx_power)
|
|
if (set->alter_tx_power_value)
|
|
vty_out(vty, " tx-power %d%s",
|
|
set->alter_tx_power_value, VTY_NEWLINE);
|
|
else
|
|
vty_out(vty, " tx-power full%s", VTY_NEWLINE);
|
|
else
|
|
if (!l23_vty_hide_default)
|
|
vty_out(vty, " tx-power auto%s", VTY_NEWLINE);
|
|
if (set->alter_delay)
|
|
vty_out(vty, " simulated-delay %d%s", set->alter_delay,
|
|
VTY_NEWLINE);
|
|
else
|
|
if (!l23_vty_hide_default)
|
|
vty_out(vty, " no simulated-delay%s", VTY_NEWLINE);
|
|
if (set->stick)
|
|
vty_out(vty, " stick %d%s%s", set->stick_arfcn & 1023,
|
|
(set->stick_arfcn & ARFCN_PCS) ? " pcs" : "",
|
|
VTY_NEWLINE);
|
|
else
|
|
if (!l23_vty_hide_default)
|
|
vty_out(vty, " no stick%s", VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->no_lupd)
|
|
vty_out(vty, " %slocation-updating%s",
|
|
(set->no_lupd) ? "no " : "", VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->no_neighbour)
|
|
vty_out(vty, " %sneighbour-measurement%s",
|
|
(set->no_neighbour) ? "no " : "", VTY_NEWLINE);
|
|
if (set->full_v1 || set->full_v2 || set->full_v3) {
|
|
/* mandatory anyway */
|
|
vty_out(vty, " codec full-speed%s%s",
|
|
(!set->half_prefer) ? " prefer" : "",
|
|
VTY_NEWLINE);
|
|
}
|
|
if (set->half_v1 || set->half_v3) {
|
|
if (set->half)
|
|
vty_out(vty, " codec half-speed%s%s",
|
|
(set->half_prefer) ? " prefer" : "",
|
|
VTY_NEWLINE);
|
|
else
|
|
vty_out(vty, " no codec half-speed%s", VTY_NEWLINE);
|
|
}
|
|
if (llist_empty(&set->abbrev)) {
|
|
if (!l23_vty_hide_default)
|
|
vty_out(vty, " no abbrev%s", VTY_NEWLINE);
|
|
} else {
|
|
llist_for_each_entry(abbrev, &set->abbrev, list)
|
|
vty_out(vty, " abbrev %s %s%s%s%s", abbrev->abbrev,
|
|
abbrev->number, (abbrev->name[0]) ? " " : "",
|
|
abbrev->name, VTY_NEWLINE);
|
|
}
|
|
vty_out(vty, " support%s", VTY_NEWLINE);
|
|
SUP_WRITE(sms_ptp, "sms");
|
|
SUP_WRITE(a5_1, "a5/1");
|
|
SUP_WRITE(a5_2, "a5/2");
|
|
SUP_WRITE(a5_3, "a5/3");
|
|
SUP_WRITE(a5_4, "a5/4");
|
|
SUP_WRITE(a5_5, "a5/5");
|
|
SUP_WRITE(a5_6, "a5/6");
|
|
SUP_WRITE(a5_7, "a5/7");
|
|
SUP_WRITE(p_gsm, "p-gsm");
|
|
SUP_WRITE(e_gsm, "e-gsm");
|
|
SUP_WRITE(r_gsm, "r-gsm");
|
|
SUP_WRITE(gsm_850, "gsm-850");
|
|
SUP_WRITE(gsm_480, "gsm-480");
|
|
SUP_WRITE(gsm_450, "gsm-450");
|
|
SUP_WRITE(dcs, "dcs");
|
|
SUP_WRITE(pcs, "pcs");
|
|
if (sup->r_gsm || sup->e_gsm || sup->p_gsm)
|
|
if (!l23_vty_hide_default || sup->class_900 != set->class_900)
|
|
vty_out(vty, " class-900 %d%s", set->class_900,
|
|
VTY_NEWLINE);
|
|
if (sup->gsm_850)
|
|
if (!l23_vty_hide_default || sup->class_850 != set->class_850)
|
|
vty_out(vty, " class-850 %d%s", set->class_850,
|
|
VTY_NEWLINE);
|
|
if (sup->gsm_480 || sup->gsm_450)
|
|
if (!l23_vty_hide_default || sup->class_400 != set->class_400)
|
|
vty_out(vty, " class-400 %d%s", set->class_400,
|
|
VTY_NEWLINE);
|
|
if (sup->dcs)
|
|
if (!l23_vty_hide_default || sup->class_dcs != set->class_dcs)
|
|
vty_out(vty, " class-dcs %d%s", set->class_dcs,
|
|
VTY_NEWLINE);
|
|
if (sup->pcs)
|
|
if (!l23_vty_hide_default || sup->class_pcs != set->class_pcs)
|
|
vty_out(vty, " class-pcs %d%s", set->class_pcs,
|
|
VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || sup->ch_cap != set->ch_cap) {
|
|
switch (set->ch_cap) {
|
|
case GSM_CAP_SDCCH:
|
|
vty_out(vty, " channel-capability sdcch%s",
|
|
VTY_NEWLINE);
|
|
break;
|
|
case GSM_CAP_SDCCH_TCHF:
|
|
vty_out(vty, " channel-capability sdcch+tchf%s",
|
|
VTY_NEWLINE);
|
|
break;
|
|
case GSM_CAP_SDCCH_TCHF_TCHH:
|
|
vty_out(vty, " channel-capability sdcch+tchf+tchh%s",
|
|
VTY_NEWLINE);
|
|
break;
|
|
}
|
|
}
|
|
SUP_WRITE(full_v1, "full-speech-v1");
|
|
SUP_WRITE(full_v2, "full-speech-v2");
|
|
SUP_WRITE(full_v3, "full-speech-v3");
|
|
SUP_WRITE(half_v1, "half-speech-v1");
|
|
SUP_WRITE(half_v3, "half-speech-v3");
|
|
if (!l23_vty_hide_default || sup->min_rxlev_dbm != set->min_rxlev_dbm)
|
|
vty_out(vty, " min-rxlev %d%s", set->min_rxlev_dbm,
|
|
VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || sup->dsc_max != set->dsc_max)
|
|
vty_out(vty, " dsc-max %d%s", set->dsc_max, VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || set->skip_max_per_band)
|
|
vty_out(vty, " %sskip-max-per-band%s",
|
|
(set->skip_max_per_band) ? "" : "no ", VTY_NEWLINE);
|
|
SUP_WRITE(vgcs, "vgcs");
|
|
SUP_WRITE(vbs, "vbs");
|
|
if (!l23_vty_hide_default || set->any_timeout != MOB_C7_DEFLT_ANY_TIMEOUT)
|
|
vty_out(vty, " c7-any-timeout %d%s",
|
|
set->any_timeout, VTY_NEWLINE);
|
|
if (!l23_vty_hide_default || !set->uplink_release_local)
|
|
vty_out(vty, " %suplink-release-local%s",
|
|
(set->uplink_release_local) ? "no " : "", VTY_NEWLINE);
|
|
|
|
vty_out(vty, " audio%s", VTY_NEWLINE);
|
|
vty_out(vty, " io-handler %s%s",
|
|
audio_io_handler_name(set->audio.io_handler), VTY_NEWLINE);
|
|
if (set->audio.io_handler == AUDIO_IOH_GAPK) {
|
|
vty_out(vty, " io-tch-format %s%s",
|
|
audio_io_format_name(set->audio.io_format), VTY_NEWLINE);
|
|
vty_out(vty, " alsa-output-dev %s%s",
|
|
set->audio.alsa_output_dev, VTY_NEWLINE);
|
|
vty_out(vty, " alsa-input-dev %s%s",
|
|
set->audio.alsa_input_dev, VTY_NEWLINE);
|
|
}
|
|
|
|
if (ms->lua_script)
|
|
vty_out(vty, " lua-script %s%s", ms->lua_script, VTY_NEWLINE);
|
|
|
|
l23_vty_config_write_ms_node_contents_final(vty, ms, " ");
|
|
}
|
|
|
|
static int config_write(struct vty *vty)
|
|
{
|
|
struct osmocom_ms *ms;
|
|
|
|
#ifdef _HAVE_GPSD
|
|
vty_out(vty, "gps host %s:%s%s", g.gpsd_host, g.gpsd_port, VTY_NEWLINE);
|
|
#endif
|
|
vty_out(vty, "gps device %s%s", g.device, VTY_NEWLINE);
|
|
if (g.baud)
|
|
vty_out(vty, "gps baudrate %d%s", g.baud, VTY_NEWLINE);
|
|
else
|
|
vty_out(vty, "gps baudrate default%s", VTY_NEWLINE);
|
|
vty_out(vty, "%sgps enable%s", (g.enable) ? "" : "no ", VTY_NEWLINE);
|
|
vty_out(vty, "!%s", VTY_NEWLINE);
|
|
|
|
vty_out(vty, "%shide-default%s", (l23_vty_hide_default) ? "" : "no ",
|
|
VTY_NEWLINE);
|
|
vty_out(vty, "!%s", VTY_NEWLINE);
|
|
|
|
llist_for_each_entry(ms, &ms_list, entity)
|
|
config_write_ms(vty, ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_show_this, cfg_ms_show_this_cmd, "show this",
|
|
SHOW_STR "Show config of this MS")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
|
|
config_write_ms(vty, ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sap, cfg_ms_sap_cmd, "sap-socket PATH",
|
|
"Define socket path to connect to SIM reader\n"
|
|
"Unix socket, default '/tmp/osmocom_sap'")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
OSMO_STRLCPY_ARRAY(set->sap_socket_path, argv[0]);
|
|
|
|
vty_restart(vty, ms);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_mncc_sock, cfg_ms_mncc_sock_cmd, "mncc-socket PATH",
|
|
"Define socket path for MNCC interface\n"
|
|
"UNIX socket path (default '/tmp/ms_mncc_' + MS_NAME)")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
OSMO_STRLCPY_ARRAY(set->mncc_socket_path, argv[0]);
|
|
|
|
vty_restart(vty, ms);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_mncc_handler, cfg_ms_mncc_handler_cmd,
|
|
"mncc-handler (internal|external|dummy)",
|
|
"Set MNCC (Call Control) handler\n"
|
|
"Built-in MNCC handler (default)\n"
|
|
"External MNCC application via UNIX-socket (e.g. LCR)\n"
|
|
"Dummy MNCC handler (no Call Control)\n")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
switch (argv[0][0]) {
|
|
case 'i':
|
|
if (set->ch_cap == GSM_CAP_SDCCH) { /* SDCCH only */
|
|
vty_out(vty, "TCH support is disabled, "
|
|
"check 'channel-capability' param%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
set->mncc_handler = MNCC_HANDLER_INTERNAL;
|
|
break;
|
|
case 'e':
|
|
set->mncc_handler = MNCC_HANDLER_EXTERNAL;
|
|
break;
|
|
case 'd':
|
|
set->mncc_handler = MNCC_HANDLER_DUMMY;
|
|
break;
|
|
default:
|
|
/* Shall not happen */
|
|
OSMO_ASSERT(0);
|
|
}
|
|
|
|
vty_restart_if_started(vty, ms);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_mncc_handler, cfg_ms_no_mncc_handler_cmd,
|
|
"no mncc-handler", NO_STR "Disable Call Control")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->mncc_handler = MNCC_HANDLER_DUMMY;
|
|
|
|
vty_restart_if_started(vty, ms);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
|
|
"Set network selection mode\nAutomatic network selection\n"
|
|
"Manual network selection")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct msgb *nmsg;
|
|
|
|
if (!ms->started) {
|
|
if (argv[0][0] == 'a')
|
|
set->plmn_mode = PLMN_MODE_AUTO;
|
|
else
|
|
set->plmn_mode = PLMN_MODE_MANUAL;
|
|
} else {
|
|
if (argv[0][0] == 'a')
|
|
nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
|
|
else
|
|
nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
|
|
if (!nmsg)
|
|
return CMD_WARNING;
|
|
gsm322_plmn_sendmsg(ms, nmsg);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_emerg_imsi, cfg_ms_emerg_imsi_cmd, "emergency-imsi IMSI",
|
|
"Use special IMSI for emergency calls\n15 digits IMSI")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
if (!osmo_imsi_str_valid(argv[0])) {
|
|
vty_out(vty, "Wrong IMSI format%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
strcpy(set->emergency_imsi, argv[0]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_emerg_imsi, cfg_ms_no_emerg_imsi_cmd, "no emergency-imsi",
|
|
NO_STR "Use IMSI of SIM or IMEI for emergency calls")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->emergency_imsi[0] = '\0';
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sms_sca, cfg_ms_sms_sca_cmd, "sms-service-center NUMBER",
|
|
"Use Service center address for outgoing SMS\nNumber of service center "
|
|
"(Use digits '0123456789*#abc', and '+' to dial international)")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
const char *number = argv[0];
|
|
|
|
if ((strlen(number) > 20 && number[0] != '+') || strlen(number) > 21) {
|
|
vty_out(vty, "Number too long%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
if (vty_check_number(vty, number))
|
|
return CMD_WARNING;
|
|
|
|
strcpy(set->sms_sca, number);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_sms_sca, cfg_ms_no_sms_sca_cmd, "no sms-service-center",
|
|
NO_STR "Use Service center address for outgoing SMS")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->sms_sca[0] = '\0';
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_sms_store, cfg_ms_no_sms_store_cmd, "no sms-store",
|
|
NO_STR "Store SMS in the home directory")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->store_sms = false;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sms_store, cfg_ms_sms_store_cmd, "sms-store",
|
|
"Store SMS in the home directory")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->store_sms = true;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_cw, cfg_ms_no_cw_cmd, "no call-waiting",
|
|
NO_STR "Disallow waiting calls")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->cw = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_cw, cfg_ms_cw_cmd, "call-waiting",
|
|
"Allow waiting calls")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->cw = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_auto_answer, cfg_ms_no_auto_answer_cmd, "no auto-answer",
|
|
NO_STR "Disable auto-answering calls")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->auto_answer = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_auto_answer, cfg_ms_auto_answer_cmd, "auto-answer",
|
|
"Enable auto-answering calls")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->auto_answer = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_force_rekey, cfg_ms_no_force_rekey_cmd, "no force-rekey",
|
|
NO_STR "Disable key renew forcing after every event")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->force_rekey = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_force_rekey, cfg_ms_force_rekey_cmd, "force-rekey",
|
|
"Enable key renew forcing after every event")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->force_rekey = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_clip, cfg_ms_clip_cmd, "clip",
|
|
"Force caller ID presentation")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->clip = 1;
|
|
set->clir = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_clir, cfg_ms_clir_cmd, "clir",
|
|
"Force caller ID restriction")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->clip = 0;
|
|
set->clir = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_clip, cfg_ms_no_clip_cmd, "no clip",
|
|
NO_STR "Disable forcing of caller ID presentation")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->clip = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_clir, cfg_ms_no_clir_cmd, "no clir",
|
|
NO_STR "Disable forcing of caller ID restriction")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->clir = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_tx_power, cfg_ms_tx_power_cmd, "tx-power (auto|full)",
|
|
"Set the way to choose transmit power\nControlled by BTS\n"
|
|
"Always full power\nFixed GSM power value if supported")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
switch (argv[0][0]) {
|
|
case 'a':
|
|
set->alter_tx_power = 0;
|
|
break;
|
|
case 'f':
|
|
set->alter_tx_power = 1;
|
|
set->alter_tx_power_value = 0;
|
|
break;
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_tx_power_val, cfg_ms_tx_power_val_cmd, "tx-power <0-31>",
|
|
"Set the way to choose transmit power\n"
|
|
"Fixed GSM power value if supported")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->alter_tx_power = 1;
|
|
set->alter_tx_power_value = atoi(argv[0]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sim_delay, cfg_ms_sim_delay_cmd, "simulated-delay <-128-127>",
|
|
"Simulate a lower or higher distance from the BTS\n"
|
|
"Delay in half bits (distance in 553.85 meter steps)")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->alter_delay = atoi(argv[0]);
|
|
gsm48_rr_alter_delay(ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_sim_delay, cfg_ms_no_sim_delay_cmd, "no simulated-delay",
|
|
NO_STR "Do not simulate a lower or higher distance from the BTS")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->alter_delay = 0;
|
|
gsm48_rr_alter_delay(ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_stick, cfg_ms_stick_cmd, "stick <0-1023> [pcs]",
|
|
"Stick to the given cell\nARFCN of the cell to stick to\n"
|
|
"Given frequency is PCS band (1900) rather than DCS band.")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
uint16_t arfcn = atoi(argv[0]);
|
|
|
|
if (argc > 1) {
|
|
if (arfcn < 512 || arfcn > 810) {
|
|
vty_out(vty, "Given ARFCN not in PCS band%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
arfcn |= ARFCN_PCS;
|
|
}
|
|
set->stick = 1;
|
|
set->stick_arfcn = arfcn;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_stick, cfg_ms_no_stick_cmd, "no stick",
|
|
NO_STR "Do not stick to any cell")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->stick = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_lupd, cfg_ms_lupd_cmd, "location-updating",
|
|
"Allow location updating")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->no_lupd = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_lupd, cfg_ms_no_lupd_cmd, "no location-updating",
|
|
NO_STR "Do not allow location updating")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->no_lupd = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_codec_full, cfg_ms_codec_full_cmd, "codec full-speed",
|
|
"Enable codec\nFull speed speech codec")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
|
|
vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_codec_full_pref, cfg_ms_codec_full_pref_cmd, "codec full-speed "
|
|
"prefer",
|
|
"Enable codec\nFull speed speech codec\nPrefer this codec")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
|
|
vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
set->half_prefer = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_codec_half, cfg_ms_codec_half_cmd, "codec half-speed",
|
|
"Enable codec\nHalf speed speech codec")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
if (!set->half_v1 && !set->half_v3) {
|
|
vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
set->half = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_codec_half_pref, cfg_ms_codec_half_pref_cmd, "codec half-speed "
|
|
"prefer",
|
|
"Enable codec\nHalf speed speech codec\nPrefer this codec")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
if (!set->half_v1 && !set->half_v3) {
|
|
vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
set->half = 1;
|
|
set->half_prefer = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_codec_half, cfg_ms_no_codec_half_cmd, "no codec half-speed",
|
|
NO_STR "Disable codec\nHalf speed speech codec")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
if (!set->half_v1 && !set->half_v3) {
|
|
vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
set->half = 0;
|
|
set->half_prefer = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_abbrev, cfg_ms_abbrev_cmd, "abbrev ABBREVIATION NUMBER [NAME]",
|
|
"Store given abbreviation number\n1-3 digits abbreviation\n"
|
|
"Number to store for the abbreviation "
|
|
"(Use digits '0123456789*#abc', and '+' to dial international)\n"
|
|
"Name of the abbreviation")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_settings_abbrev *abbrev;
|
|
int i;
|
|
|
|
llist_for_each_entry(abbrev, &set->abbrev, list) {
|
|
if (!strcmp(argv[0], abbrev->abbrev)) {
|
|
vty_out(vty, "Given abbreviation '%s' already stored, "
|
|
"delete first!%s", argv[0], VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
if (strlen(argv[0]) >= sizeof(abbrev->abbrev)) {
|
|
vty_out(vty, "Given abbreviation too long%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
for (i = 0; i < strlen(argv[0]); i++) {
|
|
if (argv[0][i] < '0' || argv[0][i] > '9') {
|
|
vty_out(vty, "Given abbreviation must have digits "
|
|
"0..9 only!%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
if (vty_check_number(vty, argv[1]))
|
|
return CMD_WARNING;
|
|
|
|
abbrev = talloc_zero(ms, struct gsm_settings_abbrev);
|
|
if (!abbrev) {
|
|
vty_out(vty, "No Memory!%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
llist_add_tail(&abbrev->list, &set->abbrev);
|
|
OSMO_STRLCPY_ARRAY(abbrev->abbrev, argv[0]);
|
|
OSMO_STRLCPY_ARRAY(abbrev->number, argv[1]);
|
|
if (argc >= 3)
|
|
OSMO_STRLCPY_ARRAY(abbrev->name, argv[2]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_no_abbrev, cfg_ms_no_abbrev_cmd, "no abbrev [ABBREVIATION]",
|
|
NO_STR "Remove given abbreviation number or all numbers\n"
|
|
"Abbreviation number to remove")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_settings_abbrev *abbrev, *abbrev2;
|
|
uint8_t deleted = 0;
|
|
|
|
llist_for_each_entry_safe(abbrev, abbrev2, &set->abbrev, list) {
|
|
if (argc < 1 || !strcmp(argv[0], abbrev->abbrev)) {
|
|
llist_del(&abbrev->list);
|
|
deleted = 1;
|
|
}
|
|
}
|
|
|
|
if (argc >= 1 && !deleted) {
|
|
vty_out(vty, "Given abbreviation '%s' not found!%s",
|
|
argv[0], VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_neighbour, cfg_ms_neighbour_cmd, "neighbour-measurement",
|
|
"Allow neighbour cell measurement in idle mode")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->no_neighbour = 0;
|
|
|
|
vty_restart_if_started(vty, ms);
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_neighbour, cfg_ms_no_neighbour_cmd, "no neighbour-measurement",
|
|
NO_STR "Do not allow neighbour cell measurement in idle mode")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->no_neighbour = 1;
|
|
|
|
vty_restart_if_started(vty, ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_any_timeout, cfg_ms_any_timeout_cmd, "c7-any-timeout <0-255>",
|
|
"Seconds to wait in C7 before doing a PLMN search")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->any_timeout = atoi(argv[0]);
|
|
|
|
vty_restart_if_started(vty, ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_uplink_release_local, cfg_ms_no_uplink_release_local_cmd, "no uplink-release-local",
|
|
NO_STR "Release L2 on uplink of VGCS channel normally. Release locally when UPLINK FREE is received.")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->uplink_release_local = false;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_uplink_release_local, cfg_ms_uplink_release_local_cmd, "uplink-release-local",
|
|
"Release L2 on uplink of VGCS channel locally after receiving UPLINK FREE.")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->uplink_release_local = true;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
static int config_write_dummy(struct vty *vty)
|
|
{
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* per support config */
|
|
DEFUN(cfg_ms_support, cfg_ms_support_cmd, "support",
|
|
"Define supported features")
|
|
{
|
|
vty->node = SUPPORT_NODE;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
#define SUP_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
|
|
DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
|
|
{ \
|
|
struct osmocom_ms *ms = vty->index; \
|
|
struct gsm_settings *set = &ms->settings; \
|
|
struct gsm_support *sup = &ms->support; \
|
|
if (!sup->item) { \
|
|
vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
|
|
if (l23_vty_reading) \
|
|
return CMD_SUCCESS; \
|
|
return CMD_WARNING; \
|
|
} \
|
|
if (restart) \
|
|
vty_restart(vty, ms); \
|
|
set->item = 1; \
|
|
return CMD_SUCCESS; \
|
|
}
|
|
|
|
#define SUP_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
|
|
DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
|
|
{ \
|
|
struct osmocom_ms *ms = vty->index; \
|
|
struct gsm_settings *set = &ms->settings; \
|
|
struct gsm_support *sup = &ms->support; \
|
|
if (!sup->item) { \
|
|
vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
|
|
if (l23_vty_reading) \
|
|
return CMD_SUCCESS; \
|
|
return CMD_WARNING; \
|
|
} \
|
|
if (restart) \
|
|
vty_restart(vty, ms); \
|
|
set->item = 0; \
|
|
return CMD_SUCCESS; \
|
|
}
|
|
|
|
#define SET_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
|
|
DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
|
|
{ \
|
|
struct osmocom_ms *ms = vty->index; \
|
|
struct gsm_settings *set = &ms->settings; \
|
|
if (restart) \
|
|
vty_restart(vty, ms); \
|
|
set->item = 1; \
|
|
return CMD_SUCCESS; \
|
|
}
|
|
|
|
#define SET_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
|
|
DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
|
|
{ \
|
|
struct osmocom_ms *ms = vty->index; \
|
|
struct gsm_settings *set = &ms->settings; \
|
|
if (restart) \
|
|
vty_restart(vty, ms); \
|
|
set->item = 0; \
|
|
return CMD_SUCCESS; \
|
|
}
|
|
|
|
SET_EN(cfg_ms_sup_dtmf, cfg_ms_sup_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
|
|
SET_DI(cfg_ms_sup_no_dtmf, cfg_ms_sup_no_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
|
|
SUP_EN(cfg_ms_sup_sms, cfg_ms_sup_sms_cmd, sms_ptp, "sms", "SMS", 0);
|
|
SUP_DI(cfg_ms_sup_no_sms, cfg_ms_sup_no_sms_cmd, sms_ptp, "sms", "SMS", 0);
|
|
SUP_EN(cfg_ms_sup_a5_1, cfg_ms_sup_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
|
|
SUP_DI(cfg_ms_sup_no_a5_1, cfg_ms_sup_no_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
|
|
SUP_EN(cfg_ms_sup_a5_2, cfg_ms_sup_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
|
|
SUP_DI(cfg_ms_sup_no_a5_2, cfg_ms_sup_no_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
|
|
SUP_EN(cfg_ms_sup_a5_3, cfg_ms_sup_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
|
|
SUP_DI(cfg_ms_sup_no_a5_3, cfg_ms_sup_no_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
|
|
SUP_EN(cfg_ms_sup_a5_4, cfg_ms_sup_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
|
|
SUP_DI(cfg_ms_sup_no_a5_4, cfg_ms_sup_no_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
|
|
SUP_EN(cfg_ms_sup_a5_5, cfg_ms_sup_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
|
|
SUP_DI(cfg_ms_sup_no_a5_5, cfg_ms_sup_no_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
|
|
SUP_EN(cfg_ms_sup_a5_6, cfg_ms_sup_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
|
|
SUP_DI(cfg_ms_sup_no_a5_6, cfg_ms_sup_no_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
|
|
SUP_EN(cfg_ms_sup_a5_7, cfg_ms_sup_a5_7_cmd, a5_7, "a5/7", "A5/7", 0);
|
|
SUP_DI(cfg_ms_sup_no_a5_7, cfg_ms_sup_no_a5_7_cmd, a5_7, "a5/7", "A5/7", 0);
|
|
SUP_EN(cfg_ms_sup_p_gsm, cfg_ms_sup_p_gsm_cmd, p_gsm, "p-gsm", "P-GSM (900)",
|
|
1);
|
|
SUP_DI(cfg_ms_sup_no_p_gsm, cfg_ms_sup_no_p_gsm_cmd, p_gsm, "p-gsm",
|
|
"P-GSM (900)", 1);
|
|
SUP_EN(cfg_ms_sup_e_gsm, cfg_ms_sup_e_gsm_cmd, e_gsm, "e-gsm", "E-GSM (850)",
|
|
1);
|
|
SUP_DI(cfg_ms_sup_no_e_gsm, cfg_ms_sup_no_e_gsm_cmd, e_gsm, "e-gsm",
|
|
"E-GSM (850)", 1);
|
|
SUP_EN(cfg_ms_sup_r_gsm, cfg_ms_sup_r_gsm_cmd, r_gsm, "r-gsm", "R-GSM (850)",
|
|
1);
|
|
SUP_DI(cfg_ms_sup_no_r_gsm, cfg_ms_sup_no_r_gsm_cmd, r_gsm, "r-gsm",
|
|
"R-GSM (850)", 1);
|
|
SUP_EN(cfg_ms_sup_dcs, cfg_ms_sup_dcs_cmd, dcs, "dcs", "DCS (1800)", 1);
|
|
SUP_DI(cfg_ms_sup_no_dcs, cfg_ms_sup_no_dcs_cmd, dcs, "dcs", "DCS (1800)", 1);
|
|
SUP_EN(cfg_ms_sup_gsm_850, cfg_ms_sup_gsm_850_cmd, gsm_850, "gsm-850",
|
|
"GSM 850", 1);
|
|
SUP_DI(cfg_ms_sup_no_gsm_850, cfg_ms_sup_no_gsm_850_cmd, gsm_850, "gsm-850",
|
|
"GSM 850", 1);
|
|
SUP_EN(cfg_ms_sup_pcs, cfg_ms_sup_pcs_cmd, pcs, "pcs", "PCS (1900)", 1);
|
|
SUP_DI(cfg_ms_sup_no_pcs, cfg_ms_sup_no_pcs_cmd, pcs, "pcs", "PCS (1900)", 1);
|
|
SUP_EN(cfg_ms_sup_gsm_480, cfg_ms_sup_gsm_480_cmd, gsm_480, "gsm-480",
|
|
"GSM 480", 1);
|
|
SUP_DI(cfg_ms_sup_no_gsm_480, cfg_ms_sup_no_gsm_480_cmd, gsm_480, "gsm-480",
|
|
"GSM 480", 1);
|
|
SUP_EN(cfg_ms_sup_gsm_450, cfg_ms_sup_gsm_450_cmd, gsm_450, "gsm-450",
|
|
"GSM 450", 1);
|
|
SUP_DI(cfg_ms_sup_no_gsm_450, cfg_ms_sup_no_gsm_450_cmd, gsm_450, "gsm-450",
|
|
"GSM 450", 1);
|
|
|
|
DEFUN(cfg_ms_sup_class_900, cfg_ms_sup_class_900_cmd, "class-900 (1|2|3|4|5)",
|
|
"Select power class for GSM 900\n"
|
|
"20 Watts\n"
|
|
"8 Watts\n"
|
|
"5 Watts\n"
|
|
"2 Watts\n"
|
|
"0.8 Watts")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_support *sup = &ms->support;
|
|
|
|
set->class_900 = atoi(argv[0]);
|
|
|
|
if (set->class_900 < sup->class_900 && !l23_vty_reading)
|
|
vty_out(vty, "Note: You selected a higher class than supported "
|
|
" by hardware!%s", VTY_NEWLINE);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_class_850, cfg_ms_sup_class_850_cmd, "class-850 (1|2|3|4|5)",
|
|
"Select power class for GSM 850\n"
|
|
"20 Watts\n"
|
|
"8 Watts\n"
|
|
"5 Watts\n"
|
|
"2 Watts\n"
|
|
"0.8 Watts")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_support *sup = &ms->support;
|
|
|
|
set->class_850 = atoi(argv[0]);
|
|
|
|
if (set->class_850 < sup->class_850 && !l23_vty_reading)
|
|
vty_out(vty, "Note: You selected a higher class than supported "
|
|
" by hardware!%s", VTY_NEWLINE);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_class_400, cfg_ms_sup_class_400_cmd, "class-400 (1|2|3|4|5)",
|
|
"Select power class for GSM 400 (480 and 450)\n"
|
|
"20 Watts\n"
|
|
"8 Watts\n"
|
|
"5 Watts\n"
|
|
"2 Watts\n"
|
|
"0.8 Watts")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_support *sup = &ms->support;
|
|
|
|
set->class_400 = atoi(argv[0]);
|
|
|
|
if (set->class_400 < sup->class_400 && !l23_vty_reading)
|
|
vty_out(vty, "Note: You selected a higher class than supported "
|
|
" by hardware!%s", VTY_NEWLINE);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_class_dcs, cfg_ms_sup_class_dcs_cmd, "class-dcs (1|2|3)",
|
|
"Select power class for DCS 1800\n"
|
|
"1 Watt\n"
|
|
"0.25 Watts\n"
|
|
"4 Watts")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_support *sup = &ms->support;
|
|
|
|
set->class_dcs = atoi(argv[0]);
|
|
|
|
if (((set->class_dcs + 1) & 3) < ((sup->class_dcs + 1) & 3)
|
|
&& !l23_vty_reading)
|
|
vty_out(vty, "Note: You selected a higher class than supported "
|
|
" by hardware!%s", VTY_NEWLINE);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_class_pcs, cfg_ms_sup_class_pcs_cmd, "class-pcs (1|2|3)",
|
|
"Select power class for PCS 1900\n"
|
|
"1 Watt\n"
|
|
"0.25 Watts\n"
|
|
"2 Watts")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_support *sup = &ms->support;
|
|
|
|
set->class_pcs = atoi(argv[0]);
|
|
|
|
if (((set->class_pcs + 1) & 3) < ((sup->class_pcs + 1) & 3)
|
|
&& !l23_vty_reading)
|
|
vty_out(vty, "Note: You selected a higher class than supported "
|
|
" by hardware!%s", VTY_NEWLINE);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_ch_cap, cfg_ms_sup_ch_cap_cmd,
|
|
"channel-capability (sdcch|sdcch+tchf|sdcch+tchf+tchh)",
|
|
"Select channel capability\n"
|
|
"SDCCH only\n"
|
|
"SDCCH + TCH/F\n"
|
|
"SDCCH + TCH/F + TCH/H")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
struct gsm_support *sup = &ms->support;
|
|
uint8_t ch_cap;
|
|
|
|
if (!strcmp(argv[0], "sdcch+tchf+tchh"))
|
|
ch_cap = GSM_CAP_SDCCH_TCHF_TCHH;
|
|
else if (!strcmp(argv[0], "sdcch+tchf"))
|
|
ch_cap = GSM_CAP_SDCCH_TCHF;
|
|
else
|
|
ch_cap = GSM_CAP_SDCCH;
|
|
|
|
if (ch_cap > sup->ch_cap && !l23_vty_reading) {
|
|
vty_out(vty, "You selected an higher capability than supported "
|
|
" by hardware!%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (ms->started && ch_cap != set->ch_cap
|
|
&& (ch_cap == GSM_CAP_SDCCH || set->ch_cap == GSM_CAP_SDCCH))
|
|
vty_restart_if_started(vty, ms);
|
|
|
|
set->ch_cap = ch_cap;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
SUP_EN(cfg_ms_sup_full_v1, cfg_ms_sup_full_v1_cmd, full_v1, "full-speech-v1",
|
|
"Full rate speech V1", 0);
|
|
SUP_DI(cfg_ms_sup_no_full_v1, cfg_ms_sup_no_full_v1_cmd, full_v1,
|
|
"full-speech-v1", "Full rate speech V1", 0);
|
|
SUP_EN(cfg_ms_sup_full_v2, cfg_ms_sup_full_v2_cmd, full_v2, "full-speech-v2",
|
|
"Full rate speech V2 (EFR)", 0);
|
|
SUP_DI(cfg_ms_sup_no_full_v2, cfg_ms_sup_no_full_v2_cmd, full_v2,
|
|
"full-speech-v2", "Full rate speech V2 (EFR)", 0);
|
|
SUP_EN(cfg_ms_sup_full_v3, cfg_ms_sup_full_v3_cmd, full_v3, "full-speech-v3",
|
|
"Full rate speech V3 (AMR)", 0);
|
|
SUP_DI(cfg_ms_sup_no_full_v3, cfg_ms_sup_no_full_v3_cmd, full_v3,
|
|
"full-speech-v3", "Full rate speech V3 (AMR)", 0);
|
|
SUP_EN(cfg_ms_sup_half_v1, cfg_ms_sup_half_v1_cmd, half_v1, "half-speech-v1",
|
|
"Half rate speech V1", 0);
|
|
SUP_DI(cfg_ms_sup_no_half_v1, cfg_ms_sup_no_half_v1_cmd, half_v1,
|
|
"half-speech-v1", "Half rate speech V1", 0);
|
|
SUP_EN(cfg_ms_sup_half_v3, cfg_ms_sup_half_v3_cmd, half_v3, "half-speech-v3",
|
|
"Half rate speech V3 (AMR)", 0);
|
|
SUP_DI(cfg_ms_sup_no_half_v3, cfg_ms_sup_no_half_v3_cmd, half_v3,
|
|
"half-speech-v3", "Half rate speech V3 (AMR)", 0);
|
|
|
|
DEFUN(cfg_ms_sup_min_rxlev, cfg_ms_sup_min_rxlev_cmd, "min-rxlev <-110--47>",
|
|
"Set the minimum receive level to select a cell\n"
|
|
"Minimum receive level from -110 dBm to -47 dBm")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->min_rxlev_dbm = atoi(argv[0]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_dsc_max, cfg_ms_sup_dsc_max_cmd, "dsc-max <90-500>",
|
|
"Set the maximum DSC value. Standard is 90. Increase to make mobile "
|
|
"more reliable against bad RX signal. This increase the propability "
|
|
"of missing a paging requests\n"
|
|
"DSC initial and maximum value (standard is 90)")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->dsc_max = atoi(argv[0]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_skip_max_per_band, cfg_ms_sup_skip_max_per_band_cmd,
|
|
"skip-max-per-band",
|
|
"Scan all frequencies per band, not only a maximum number")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->skip_max_per_band = 1;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_sup_no_skip_max_per_band, cfg_ms_sup_no_skip_max_per_band_cmd,
|
|
"no skip-max-per-band",
|
|
NO_STR "Scan only a maximum number of frequencies per band")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
set->skip_max_per_band = 0;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
SUP_EN(cfg_ms_sup_vgcs, cfg_ms_sup_vgcs_cmd, vgcs, "vgcs",
|
|
"Voice Group Call Service (VGCS)", 0);
|
|
SUP_DI(cfg_ms_sup_no_vgcs, cfg_ms_sup_no_vgcs_cmd, vgcs,
|
|
"vgcs", "Voice Group Call Service (VBS)", 0);
|
|
SUP_EN(cfg_ms_sup_vbs, cfg_ms_sup_vbs_cmd, vbs, "vbs",
|
|
"Voice Broadcast Service (VBS)", 0);
|
|
SUP_DI(cfg_ms_sup_no_vbs, cfg_ms_sup_no_vbs_cmd, vbs,
|
|
"vbs", "Voice Broadcast Service (VBS)", 0);
|
|
|
|
/* per audio config */
|
|
DEFUN(cfg_ms_audio, cfg_ms_audio_cmd, "audio",
|
|
"Configure audio settings")
|
|
{
|
|
vty->node = AUDIO_NODE;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
static int set_audio_io_handler(struct vty *vty, enum audio_io_handler val)
|
|
{
|
|
struct osmocom_ms *ms = (struct osmocom_ms *) vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
/* Don't restart on unchanged value */
|
|
if (val == set->audio.io_handler)
|
|
return CMD_SUCCESS;
|
|
set->audio.io_handler = val;
|
|
|
|
/* Restart required */
|
|
vty_restart_if_started(vty, ms);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_audio_io_handler, cfg_ms_audio_io_handler_cmd,
|
|
"io-handler (none|gapk|l1phy|mncc-sock|loopback)",
|
|
"Set TCH frame I/O handler\n"
|
|
"No handler, drop TCH frames (default)\n"
|
|
"libosmo-gapk based I/O handler (requires ALSA)\n"
|
|
"L1 PHY (e.g. Calypso DSP in Motorola C1xx phones)\n"
|
|
"External MNCC application (e.g. LCR) via MNCC socket\n"
|
|
"Return TCH frame payload back to sender\n")
|
|
{
|
|
struct osmocom_ms *ms = (struct osmocom_ms *) vty->index;
|
|
int val = get_string_value(audio_io_handler_names, argv[0]);
|
|
|
|
if (val == AUDIO_IOH_MNCC_SOCK) {
|
|
if (ms->settings.mncc_handler != MNCC_HANDLER_INTERNAL) {
|
|
vty_out(vty, "Audio I/O handler 'mncc-sock' can only be used "
|
|
"with MNCC handler 'external'%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
#ifndef WITH_GAPK_IO
|
|
if (val == AUDIO_IOH_GAPK) {
|
|
vty_out(vty, "GAPK I/O is not compiled in (--with-gapk-io)%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
#endif
|
|
|
|
return set_audio_io_handler(vty, val);
|
|
}
|
|
|
|
DEFUN(cfg_ms_audio_no_io_handler, cfg_ms_audio_no_io_handler_cmd,
|
|
"no io-handler", NO_STR "Disable TCH frame processing")
|
|
{
|
|
return set_audio_io_handler(vty, AUDIO_IOH_NONE);
|
|
}
|
|
|
|
DEFUN(cfg_ms_audio_io_tch_format, cfg_ms_audio_io_tch_format_cmd,
|
|
"io-tch-format (rtp|ti)",
|
|
"Set TCH I/O frame format used by the L1 PHY (for GAPK only)\n"
|
|
"RTP format (RFC3551 for FR/EFR, RFC5993 for HR, RFC4867 for AMR)\n"
|
|
"Texas Instruments format, used by Calypso based phones (e.g. Motorola C1xx)\n")
|
|
{
|
|
int val = get_string_value(audio_io_format_names, argv[0]);
|
|
struct osmocom_ms *ms = (struct osmocom_ms *) vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
if (set->audio.io_handler != AUDIO_IOH_GAPK) {
|
|
vty_out(vty, "This parameter is only valid for GAPK%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
OSMO_ASSERT(val >= 0);
|
|
set->audio.io_format = val;
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_audio_alsa_out_dev, cfg_ms_audio_alsa_out_dev_cmd,
|
|
"alsa-output-dev (default|NAME)",
|
|
"Set ALSA output (playback) device name (for GAPK only)\n"
|
|
"Default system playback device (default)\n"
|
|
"Name of a custom playback device")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
OSMO_STRLCPY_ARRAY(set->audio.alsa_output_dev, argv[0]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_audio_alsa_in_dev, cfg_ms_audio_alsa_in_dev_cmd,
|
|
"alsa-input-dev (default|NAME)",
|
|
"Set ALSA input (capture) device name (for GAPK only)\n"
|
|
"Default system recording device (default)\n"
|
|
"Name of a custom recording device")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
struct gsm_settings *set = &ms->settings;
|
|
|
|
OSMO_STRLCPY_ARRAY(set->audio.alsa_input_dev, argv[0]);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_script_load_run, cfg_ms_script_load_run_cmd, "lua-script FILENAME",
|
|
"Load and execute a LUA script\nFilename for lua script")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
|
|
osmo_talloc_replace_string(ms, &ms->lua_script, argv[0]);
|
|
if (!ms->lua_script)
|
|
return CMD_WARNING;
|
|
|
|
script_lua_load(vty, ms, ms->lua_script);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(cfg_ms_no_script_load_run, cfg_ms_no_script_load_run_cmd, "no lua-script",
|
|
NO_STR "Load and execute LUA script")
|
|
{
|
|
struct osmocom_ms *ms = vty->index;
|
|
|
|
script_lua_close(ms);
|
|
talloc_free(ms->lua_script);
|
|
ms->lua_script = NULL;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN(off, off_cmd, "off",
|
|
"Turn mobiles off (shutdown) and exit")
|
|
{
|
|
osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
/* run ms instance, if layer1 is available */
|
|
static int l23_vty_signal_cb(unsigned int subsys, unsigned int signal,
|
|
void *handler_data, void *signal_data)
|
|
{
|
|
struct osmobb_l23_vty_sig_data *d = signal_data;
|
|
struct vty *vty = d->vty;
|
|
char *other_name = NULL;
|
|
int rc;
|
|
|
|
if (subsys != SS_L23_VTY)
|
|
return 0;
|
|
|
|
switch (signal) {
|
|
case S_L23_VTY_MS_START:
|
|
rc = mobile_start(d->ms_start.ms, &other_name);
|
|
switch (rc) {
|
|
case -1:
|
|
vty_out(vty, "Cannot start MS '%s', because MS '%s' "
|
|
"use the same layer2-socket.%sPlease shutdown "
|
|
"MS '%s' first.%s", d->ms_start.ms->name, other_name,
|
|
VTY_NEWLINE, other_name, VTY_NEWLINE);
|
|
break;
|
|
case -2:
|
|
vty_out(vty, "Cannot start MS '%s', because MS '%s' "
|
|
"use the same sap-socket.%sPlease shutdown "
|
|
"MS '%s' first.%s", d->ms_start.ms->name, other_name,
|
|
VTY_NEWLINE, other_name, VTY_NEWLINE);
|
|
break;
|
|
case -3:
|
|
vty_out(vty, "Connection to layer 1 failed!%s",
|
|
VTY_NEWLINE);
|
|
break;
|
|
}
|
|
d->ms_start.rc = (rc == 0) ? CMD_SUCCESS : CMD_WARNING;
|
|
break;
|
|
case S_L23_VTY_MS_STOP:
|
|
mobile_stop(d->ms_stop.ms, d->ms_stop.force);
|
|
d->ms_start.rc = CMD_SUCCESS;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
#define SUP_NODE(item) \
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_item_cmd);
|
|
|
|
int ms_vty_init(void)
|
|
{
|
|
int rc;
|
|
|
|
if ((rc = l23_vty_init(config_write, l23_vty_signal_cb)) < 0)
|
|
return rc;
|
|
|
|
install_element_ve(&show_ms_cmd);
|
|
install_element_ve(&show_cell_cmd);
|
|
install_element_ve(&show_cell_si_cmd);
|
|
install_element_ve(&show_nbcells_cmd);
|
|
install_element_ve(&show_ba_cmd);
|
|
install_element_ve(&show_forb_la_cmd);
|
|
install_element_ve(&show_forb_plmn_cmd);
|
|
install_element_ve(&show_asci_calls_cmd);
|
|
install_element_ve(&show_asci_neighbors_cmd);
|
|
install_element_ve(&monitor_network_cmd);
|
|
install_element_ve(&no_monitor_network_cmd);
|
|
install_element(ENABLE_NODE, &off_cmd);
|
|
|
|
install_element(ENABLE_NODE, &network_search_cmd);
|
|
install_element(ENABLE_NODE, &network_show_cmd);
|
|
install_element(ENABLE_NODE, &network_select_cmd);
|
|
install_element(ENABLE_NODE, &call_cmd);
|
|
install_element(ENABLE_NODE, &call_retr_cmd);
|
|
install_element(ENABLE_NODE, &call_dtmf_cmd);
|
|
install_element(ENABLE_NODE, &sms_cmd);
|
|
install_element(ENABLE_NODE, &service_cmd);
|
|
install_element(ENABLE_NODE, &vgcs_enter_cmd);
|
|
install_element(ENABLE_NODE, &vgcs_direct_cmd);
|
|
install_node(&vgcs_node, config_write_dummy);
|
|
install_element(VGCS_NODE, &vgcs_cmd);
|
|
install_element(ENABLE_NODE, &vbs_enter_cmd);
|
|
install_element(ENABLE_NODE, &vbs_direct_cmd);
|
|
install_node(&vbs_node, config_write_dummy);
|
|
install_element(VBS_NODE, &vbs_cmd);
|
|
install_element(ENABLE_NODE, &test_reselection_cmd);
|
|
install_element(ENABLE_NODE, &delete_forbidden_plmn_cmd);
|
|
|
|
#ifdef _HAVE_GPSD
|
|
install_element(CONFIG_NODE, &cfg_gps_host_cmd);
|
|
#endif
|
|
install_element(CONFIG_NODE, &cfg_gps_device_cmd);
|
|
install_element(CONFIG_NODE, &cfg_gps_baud_cmd);
|
|
install_element(CONFIG_NODE, &cfg_gps_enable_cmd);
|
|
install_element(CONFIG_NODE, &cfg_no_gps_enable_cmd);
|
|
|
|
install_element(CONFIG_NODE, &cfg_ms_cmd);
|
|
install_element(CONFIG_NODE, &cfg_ms_create_cmd);
|
|
install_element(CONFIG_NODE, &cfg_ms_rename_cmd);
|
|
install_element(CONFIG_NODE, &cfg_no_ms_cmd);
|
|
|
|
/* MS_NODE is installed by l23_vty_init(). App specific commands below: */
|
|
install_element(MS_NODE, &cfg_ms_show_this_cmd);
|
|
install_element(MS_NODE, &cfg_ms_sap_cmd);
|
|
install_element(MS_NODE, &cfg_ms_mncc_sock_cmd);
|
|
install_element(MS_NODE, &cfg_ms_mncc_handler_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_mncc_handler_cmd);
|
|
install_element(MS_NODE, &cfg_ms_mode_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_emerg_imsi_cmd);
|
|
install_element(MS_NODE, &cfg_ms_emerg_imsi_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_sms_sca_cmd);
|
|
install_element(MS_NODE, &cfg_ms_sms_sca_cmd);
|
|
install_element(MS_NODE, &cfg_ms_cw_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_cw_cmd);
|
|
install_element(MS_NODE, &cfg_ms_auto_answer_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_auto_answer_cmd);
|
|
install_element(MS_NODE, &cfg_ms_force_rekey_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_force_rekey_cmd);
|
|
install_element(MS_NODE, &cfg_ms_clip_cmd);
|
|
install_element(MS_NODE, &cfg_ms_clir_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_clip_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_clir_cmd);
|
|
install_element(MS_NODE, &cfg_ms_tx_power_cmd);
|
|
install_element(MS_NODE, &cfg_ms_tx_power_val_cmd);
|
|
install_element(MS_NODE, &cfg_ms_sim_delay_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_sim_delay_cmd);
|
|
install_element(MS_NODE, &cfg_ms_stick_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_stick_cmd);
|
|
install_element(MS_NODE, &cfg_ms_lupd_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_lupd_cmd);
|
|
install_element(MS_NODE, &cfg_ms_codec_full_cmd);
|
|
install_element(MS_NODE, &cfg_ms_codec_full_pref_cmd);
|
|
install_element(MS_NODE, &cfg_ms_codec_half_cmd);
|
|
install_element(MS_NODE, &cfg_ms_codec_half_pref_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_codec_half_cmd);
|
|
install_element(MS_NODE, &cfg_ms_abbrev_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_abbrev_cmd);
|
|
install_element(MS_NODE, &cfg_ms_audio_cmd);
|
|
install_element(MS_NODE, &cfg_ms_neighbour_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_neighbour_cmd);
|
|
install_element(MS_NODE, &cfg_ms_any_timeout_cmd);
|
|
install_element(MS_NODE, &cfg_ms_sms_store_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_sms_store_cmd);
|
|
install_element(MS_NODE, &cfg_ms_uplink_release_local_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_uplink_release_local_cmd);
|
|
install_element(MS_NODE, &cfg_ms_support_cmd);
|
|
install_node(&support_node, config_write_dummy);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_dtmf_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_dtmf_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_sms_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_sms_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_1_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_1_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_2_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_2_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_3_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_3_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_4_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_4_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_5_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_5_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_6_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_6_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_a5_7_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_7_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_p_gsm_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_p_gsm_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_e_gsm_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_e_gsm_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_r_gsm_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_r_gsm_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_dcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_dcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_850_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_850_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_pcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_pcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_480_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_480_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_450_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_450_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_class_900_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_class_dcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_class_850_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_class_pcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_class_400_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_ch_cap_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_full_v1_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v1_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_full_v2_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v2_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_full_v3_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v3_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_half_v1_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v1_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_half_v3_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v3_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_min_rxlev_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_dsc_max_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_skip_max_per_band_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_skip_max_per_band_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_vgcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_vgcs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_vbs_cmd);
|
|
install_element(SUPPORT_NODE, &cfg_ms_sup_no_vbs_cmd);
|
|
install_element(MS_NODE, &cfg_ms_script_load_run_cmd);
|
|
install_element(MS_NODE, &cfg_ms_no_script_load_run_cmd);
|
|
|
|
install_node(&audio_node, config_write_dummy);
|
|
install_element(AUDIO_NODE, &cfg_ms_audio_io_handler_cmd);
|
|
install_element(AUDIO_NODE, &cfg_ms_audio_no_io_handler_cmd);
|
|
install_element(AUDIO_NODE, &cfg_ms_audio_io_tch_format_cmd);
|
|
install_element(AUDIO_NODE, &cfg_ms_audio_alsa_out_dev_cmd);
|
|
install_element(AUDIO_NODE, &cfg_ms_audio_alsa_in_dev_cmd);
|
|
|
|
return 0;
|
|
}
|
|
|